在我正在合作的一个项目中,我们有两种选择可以使用哪个module系统:
- 导入使用的module
require
,并使用导出module.exports
和exports.foo
。 - 使用 ES6 导入module,使用 ES6
import
导出export
使用其中一种是否有任何性能优势?如果我们要使用 ES6 module而不是 Node module,还有什么我们应该知道的吗?
在我正在合作的一个项目中,我们有两种选择可以使用哪个module系统:
require
,并使用导出module.exports
和exports.foo
。import
导出export
使用其中一种是否有任何性能优势?如果我们要使用 ES6 module而不是 Node module,还有什么我们应该知道的吗?
自 Node v12(2019 年 4 月)以来,默认启用对 ES module的支持,自 Node v15(2020 年 10 月)以来它是稳定的(请参阅此处)。包含节点module.mjs
的package.json
文件必须以"type": "module"
. 该节点的文件有一吨的详细信息,还约CommonJS的和ESmodule之间的互操作。
在性能方面,新功能总是有可能不如现有功能优化得那么好。然而,由于module文件只评估一次,性能方面可能会被忽略。最后,无论如何,您都必须运行基准测试才能获得明确的答案。
ES module可以通过该import()
函数动态加载。与 不同require
,这会返回一个Promise。
使用其中一种是否有任何性能优势?
请记住,目前还没有原生支持 ES6 module的 JavaScript 引擎。你自己说你正在使用 Babel。无论如何,Babel 都会默认转换import
并export
声明为 CommonJS ( require
/ module.exports
)。因此,即使您使用 ES6 module语法,如果您在 Node.js 中运行代码,您也会在幕后使用 CommonJS。
CommonJS 和 ES6 module之间存在技术差异,例如 CommonJS 允许您动态加载module。ES6 不允许这样做,但是有一个正在开发的 API。
由于 ES6 module是标准的一部分,我会使用它们。
您可能需要考虑多种用途/功能:
要求:
require
s,它们将被一一加载和处理。ES6 导入:
此外,Require module系统不是基于标准的。既然存在 ES6 module,它就不太可能成为标准。未来将在各种实现中原生支持 ES6 module,这将在性能方面具有优势。
就目前 ES6 导入而言,导出始终编译为 CommonJS,因此使用其中之一没有任何好处。虽然推荐使用 ES6,因为当浏览器的本机支持发布时它应该是有利的。原因是,您可以从一个文件导入部分文件,而使用 CommonJS,您必须需要所有文件。
ES6 → import, export default, export
CommonJS → require, module.exports, exports.foo
以下是这些的常见用法。
ES6 导出默认
// hello.js
function hello() {
return 'hello'
}
export default hello
// app.js
import hello from './hello'
hello() // returns hello
ES6导出多个导入多个
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
export { hello1, hello2 }
// app.js
import { hello1, hello2 } from './hello'
hello1() // returns hello1
hello2() // returns hello2
CommonJS module.exports
// hello.js
function hello() {
return 'hello'
}
module.exports = hello
// app.js
const hello = require('./hello')
hello() // returns hello
CommonJS module.exports 多个
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
module.exports = {
hello1,
hello2
}
// app.js
const hello = require('./hello')
hello.hello1() // returns hello1
hello.hello2() // returns hello2
主要优点是语法:
您不太可能看到 ES6 module的任何性能优势。即使浏览器完全支持 ES6 功能,您仍然需要一个额外的库来捆绑module。
使用其中一种是否有任何性能优势?
当前的答案是否定的,因为当前的浏览器引擎都没有实现import/export
ES6 标准。
一些对比图http://kangax.github.io/compat-table/es6/没有考虑到这一点,所以当你看到Chrome几乎所有的绿色时,小心点。import
ES6 中的关键字尚未考虑在内。
换句话说,包括 V8 在内的当前浏览器引擎无法通过任何 JavaScript 指令从主 JavaScript 文件导入新的 JavaScript 文件。
(在V8 根据 ES6 规范实现它之前,我们可能还有一些错误或几年之后。)
ES6 标准说在我们读取module之前应该有module依赖项,就像在编程语言 C 中一样,我们有(头文件).h
文件。
这是一个良好且经过充分测试的结构,我相信创建 ES6 标准的专家考虑到了这一点。
这使得 Webpack 或其他包打包器能够在某些特殊情况下优化包,并减少包中不需要的一些依赖项。但是如果我们有完美的依赖关系,这永远不会发生。
import/export
原生支持上线还需要一些时间,而且require
关键字在很长一段时间内都不会去任何地方。
什么是require
?
这是node.js
加载module的方式。( https://github.com/nodejs/node )
Node 使用系统级方法来读取文件。使用require
. require
将在一些系统调用uv_fs_open
(取决于最终系统、Linux、Mac、Windows)中结束以加载 JavaScript 文件/module。
要检查这是否属实,请尝试使用 Babel.js,您将看到import
关键字将转换为require
.