随着现代 Web 开发,我们要么使用 require 要么使用 import 引用 JAVAScript 依赖项。有时,我们将两者结合使用。
但是,你知道为什么这两者都存在吗? 使用一种或另一种时的最佳实践是什么?
在本文中,我将讨论使用 require 和 import 并回答其中一些常见问题。
在讨论 require 和 import 之前,有必要对 JavaScript 模块有一定的了解。 那么,让我们看看有哪些不同类型的 JavaScript 模块可用。
引入了 AMD 模块以使模块更加前端友好。 它们不需要任何打包器,并且所有依赖项都是动态解析的。
AMD使用 require 函数用于加载外部模块,并且能够充当 CommonJS 模块的包装器。
define("exampleModule", [], () => {
return {
print: () => console.log("Hello World!");
}
}
define("main", ["require", "exampleModule"], (require) => {
const exampleModule= require("exampleModule");
exampleModule.print();
});
但是,随着 ES 模块的引入,AMD 的使用量急剧减少。
CommonJS 是 NodeJS 用来在模块中封装 JavaScript 的标准。 module.exports用于导出 CommonJS 模块,以及 import 函数用于将模块包含到单独的文件中。
尽管 CommonJS 模块在 NodeJS 中被广泛使用,但在前端开发中并没有使用它们。 这背后的主要原因是require函数的同步行为。
但是,NodeJS 从 v13 开始才开始支持 ES 模块。 在那之前,大多数 NodeJS 模块,包括 NPM 库,都是使用 CommonJS 模块开发的。
因此,CommonJS 模块仍然在开发人员中广泛使用。
而且,CommonJS 模块与 ES 模块同样重要,我将在本文接下来的部分中讨论更多。
UMD 是 AMD 和 CommonJS 的组合。 它使用了 AMD 的 CommonJS 语法和异步加载技术,使其适用于服务器端和客户端。
UMD 在 Webpack 等打包器中用作回退模块,下面显示了一个简单的 UMD 模块示例:
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(["jquery"], factory); // AMD } else if (typeof exports === "object" ) { module.exports = factory(require("jquery")); //CommonJS } else { root.returnExports = factory(root.jQuery); }
})(this, function ($) {
function exampleFunction() {}
return exampleFunction;
});
ES Modules (ECMAScript Modules) 是 JavaScript 中使用的官方标准。 ES 模块使用 import和 export 处理模块的语句。 它解决了 CommonJS 的最大限制之一,即同步加载。
在引入 ES Modules 之后,开发者之间有很多争论,考虑到与 CommonJS 的兼容性。 但是,开发人员已经适应使用这两种方法,我们将在接下来的部分中讨论更多详细信息。
已经了解了 JavaScript 模块的背景,那么让我们继续讨论 require 和 import.
require通常与 NodeJS 一起使用来读取和执行 CommonJS 模块。
这些模块可以是内置模块,如 http或自定义编写的模块。 使用 require,可以将它们包含在 JavaScript 文件中并使用它们的函数和变量。
// 内置模块
const http= require('http');
// 本地模块
const getBlogName = require('./blogDetails.js')
但是,如果要使用 require 要获取本地模块,首先需要使用 module.exports 导出它们.
例如,假设您有一个名为 blogDetails.js,并且您需要使用该文件中的函数 index.js文件。
// blogDetails.js
const getBlogTitle = (name, author) => {
return name + " by " + author;
}
modules.export = getBlogTitle;
// index.js
const getBlogTitle = require('./blogDetails.js');
var title = getBlogTitle ('Require vs Import in JavaScript', 'Chameera Dulanga');
还可以使用一次导出多个模块 modules.export 如下:
const getBlogTitle = (name, author) => {
return name + " by " + author;
}
const getBlogContent = () => {
return content
}
modules.export = {
getBlogTitle,
getBlogContent,
};
注意: 如果最后不是使用 modules.export,可以附加 exports 。 例如: exports.getBlogContent = () => {};
我想现在你明白什么时候应该使用 require以及它是如何工作的。 接下来让我们看看如何 import 。 然后我们将能够以更深层次的理解来比较和对比它们。
import 是一个 ES 模块,并带有 export,它们被称为 ES6 import 和 export.
我们不能用 import 或导出到 ES 模块之外。
试图 import ES 模块之外是一个常见的开发人员错误。
如果我举同样的例子,我需要做的唯一改变就是修改 modules.export到 export default.
const getBlogTitle = (name, author) => {
return name + " by " + author;
}
export default getBlogTitle;
然后我们可以使用 import 将此文件包含在我们的 index.js文件。
import getBlogTitle from "./blogDetails.js";
var title = getBlogTitle ('Require vs Import in JavaScript', 'Chameera Dulanga');
注意: 类似于 require,还可以通过将导出附加到每个函数定义来单独导出每个函数。
例如: export const = getBlogContent = () => {};
所以,我想你现在明白应该如何以及何时使用 require和 import。但是,这还不是全部; 它们的功能和用法存在一些显着差异。 是时候进行比较了。
require 和 import 都用于包含模块。 但是它们有几个应该注意的重要功能。
import 语句只能在文件的开头定义。 定义一个 import 其他地方的语句会给你一个错误或自动转移到文件的开头。
声明 require 时,当加载的模块名称未预定义时,允许有条件地或动态地加载模块。
例如,你可以调用 require 在函数或 if 条件中,如下所示:
if(articleCount>0){
const getBlogTitle = require(‘./blogDetails.js’);
}
require语句具有这种灵活性,因为它们被视为函数。 它们在运行时被调用,在此之前没有办法知道任何事情。 但, import 语句是静态的,我们不能有条件地或动态地使用它们。
注意: 由于 import 语句是静态的,所以可以在运行应用程序之前检测到任何错误
在小型应用程序中,同步或异步可能不会发挥主要作用。 但是,如果我们考虑大型应用程序,则会使用数百个模块。 所以,如果你使用 require, 模块将被一 一加载和处理。
而 import 语句通过异步工作解决了这个问题,这比 require 在大规模应用中更能发挥作用。
正如我们所讨论的,ES 模块系统是作为维护客户端 JavaScript 模块的标准引入的。 TypeScript 也采用了它,并添加了用于定义 Type 的内容。 因此,我不认为 require可以再次取代 ES,因为它已成为开发人员中广泛使用的标准。
但是由于有大量的 NodeJS 模块和库是用 CommonJS 编写的,我们不能保留 require完全放在一边。 所以我们必须相应地使用它们。
如果你使用的是 TypeScript,则可以通过配置 tsconfig.json文件。 例如,假设我们需要输出一个使用 CommonJS 的代码版本。
需要做的就是创建一个新的 tsconfig 通过扩展原始文件用于 CommonJS 输出 tsconfig文件并修改 module下参数 CompilerOptions.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"outDir": "./lib/cjs"
},
}
注意: 还可以使用 Webpack 等构建工具将 ES 模块转换为 CommonJS 模块。
以下表格为比较两者
特征 |
require |
import |
语法 |
const x=require() |
import x from './' |
模块 |
CommonJS |
ES |
异步 |
不支持 |
支持 |
条件(if) |
支持 |
不支持 |
Node |
支持 |
V13+ |
TypeScript |
支持 |
支持 |