Answers:
一项使用另一项有什么性能上的好处?
请记住,还没有JavaScript引擎本身支持ES6模块。您说自己正在使用Babel。无论如何,Babel都会默认将其转换import
并export
声明为CommonJS(require
/ module.exports
)。因此,即使您使用ES6模块语法,但如果在Node中运行代码,也将在后台使用CommonJS。
CommonJS和ES6模块之间存在技术差异,例如,CommonJS允许您动态加载模块。ES6不允许这样做,但是正在为此开发一个API。
由于ES6模块是标准的一部分,因此我将使用它们。
ES6 import
,require
但它们的工作方式有所不同。CommonJS导出类本身,而只有一个类。ES6导出就像有多个类,因此您必须使用它.ClassName
来获取导出的类。还有其他实际影响实现的差异
module.exports = ...;
等同于export default ...
。exports.foo = ...
等价于export var foo = ...
;
import
在Webpack 2 / Rollup(以及其他允许ES6摇树的捆绑器)中最终使用Node.b编译为Node.com 中的CommonJS,也有可能最终完成一个文件,该文件明显小于等效的Node Node处理代码。require
正是由于 ES6允许对导入/导出进行静态分析这一事实,所以才使用它们。尽管这对Node并没有什么影响,但如果最终将代码作为单个浏览器捆绑包出售,肯定可以。
您可能要考虑几种用法/功能:
要求:
require
,它们将被一个接一个地加载和处理。ES6导入:
另外,Require模块系统也不基于标准。由于存在ES6模块,因此极不可能成为标准。将来,将在各种实现中对ES6模块提供本机支持,这将在性能方面带来优势。
require
无论如何都可能将ES6模块编译为,因此无论如何都在使用Node的模块系统和加载器。
主要优点是语法:
您不太可能看到ES6模块的任何性能优势。即使浏览器完全支持ES6功能,您仍将需要一个额外的库来捆绑模块。
node --experimemntal-modules index.mjs
让您import
无需Babel即可使用。您还可以(并且应该)将npm软件包发布为本机ESModule,并向后兼容旧require
方法。许多浏览器本身也支持动态导入。
一项使用另一项有什么性能上的好处?
当前的答案是否定的,因为当前的浏览器引擎都没有实现import/export
ES6标准。
一些比较表http://kangax.github.io/compat-table/es6/没有考虑到这一点,因此当您看到Chrome的几乎所有绿色时,请小心。import
未考虑来自ES6的关键字。
换句话说,包括V8在内的当前浏览器引擎无法通过任何JavaScript指令从主JavaScript文件导入新的JavaScript文件。
(直到V8根据ES6规范实现该功能为止,我们距离我们可能只有几步之遥,也可能只有数年之遥。)
ES6标准说,在像使用编程语言C那样拥有(头文件).h
文件的方式读取模块之前,应该存在模块依赖性。
这是一个经过良好测试的良好结构,并且我相信创建ES6标准的专家会牢记这一点。
这就是使Webpack或其他程序包捆绑器在某些特殊情况下可以优化该程序包,并减少该程序包不需要的某些依赖项的原因。但是,如果我们有完美的依赖关系,这将永远不会发生。
import/export
原生支持尚需时日,而require
关键字很长一段时间都不会出现。
什么require
啊
这是node.js
加载模块的方式。(https://github.com/nodejs/node)
Node使用系统级方法来读取文件。使用时,基本上可以依靠它require
。require
将以某些系统调用uv_fs_open
(取决于最终系统,Linux,Mac,Windows)结束,以加载JavaScript文件/模块。
要检查这是否正确,请尝试使用Babel.js,您会看到该import
关键字将转换为require
。
import
在Webpack 2 /汇总构建过程中使用,可以通过“摇晃”未使用的模块/代码来减小生成的文件大小,否则这些文件/代码可能会在最终捆绑包中结清。较小的文件大小=下载速度更快=在客户端上初始化/执行速度更快。
import
关键字本地使用。或这意味着您无法从JavaScript文件导入另一个JavaScript文件。这就是为什么您无法比较这两者的性能优势的原因。但是,当然,Webpack1 / 2或Browserify之类的工具可以处理压缩。他们并驾齐驱:gist.github.com/substack/68f8d502be42d5cd4942
import
和export
是导入特定代码路径的静态声明,而require
可以是动态的,因此可以捆绑在未使用的代码中。性能收益是间接的-Webpack 2和/或汇总可以潜在地导致较小的包大小,这些包大小可以更快地下载,因此对于(浏览器的)最终用户来说显得更灵活。仅当所有代码都写在ES6模块中,因此导入才可以静态分析时,此方法才有效。
import/export
转换为require
,被授予。但是在此步骤之前发生的事情可以被认为是“性能”增强。示例:如果lodash
用ES6和you编写import { omit } from lodash
,则最终捆绑包将仅包含“忽略”,而不包含其他实用程序,而简单捆绑包require('lodash')
将导入所有内容。这将增加捆绑包的大小,需要更长的下载时间,从而降低性能。当然,这仅在浏览器上下文中有效。
使用ES6模块对于“摇树”很有用;例如,启用Webpack 2,汇总(或其他捆绑程序)以标识未使用/导入的代码路径,因此不要将其放入生成的捆绑程序中。通过消除不需要的代码,可以大大减少文件的大小,但是CommonJS是默认捆绑的,因为Webpack等无法知道是否需要它。
这是通过对代码路径进行静态分析来完成的。
例如,使用:
import { somePart } 'of/a/package';
...给捆绑程序一个package.anotherPart
不需要的提示(如果未导入,则无法使用-对吗?),因此不会打扰它。
要为Webpack 2启用此功能,您需要确保您的编译器不会吐出CommonJS模块。如果您将es2015
插件与babel一起使用,则可以按以下方式禁用它.babelrc
:
{
"presets": [
["es2015", { modules: false }],
]
}
汇总和其他工具的工作方式可能有所不同-如果您有兴趣,请查看文档。
当涉及到异步或延迟加载时,它的功能要强import ()
大得多。看看何时我们需要异步方式的组件,然后我们import
以某种异步方式使用它,就像在const
using中使用变量一样await
。
const module = await import('./module.js');
或者,如果您想使用require()
,
const converter = require('./converter');
事情是import()
实际上是异步的性质。正如neehar neehar venugopal在ReactConf中提到的那样,您可以使用它为客户端架构动态加载React组件。
在路由方面也更好。这是当用户将特定网站连接到其特定组件时使网络日志下载必要部分的一件事。例如,在仪表板无法下载仪表板的所有组件之前的登录页面。因为当前需要什么,即登录组件,所以将仅下载该组件。
这同样适用于export
:ES6 export
是为CommonJS的完全相同module.exports
。
注意 -如果你正在开发一个项目的Node.js,那么你必须严格使用require()
的节点会抛出异常错误的invalid token 'import'
,如果你会使用import
。因此,节点不支持导入语句。
更新-正如Dan Dascalescu所建议:自v8.5.0(2017年9月发布)以来,node --experimental-modules index.mjs
您import
无需Babel即可使用。您还可以(并且应该)将npm软件包发布为本机ESModule,并向后兼容 旧require
方法。
有关在哪里使用异步导入的更多信息,请参见此-https: //www.youtube.com/watch?v=bb6RCrDaxhw
最重要的是,ES6模块确实是一个官方标准,而CommonJS(Node.js)模块则不是。
在2019年,84%的浏览器都支持ES6模块。尽管Node.js将它们放在--experimental-modules标志的后面,但还有一个方便的节点程序包esm,它使集成更加流畅。
您可能会在这些模块系统之间遇到的另一个问题是代码位置。Node.js假定源代码保存在node_modules
目录中,而大多数ES6模块则以平面目录结构进行部署。这些都不容易调和,但是可以通过package.json
使用安装前和安装后脚本来入侵文件来完成。下面是一个例子同构模块和文章解释它是如何工作的。
我个人使用import是因为,我们可以使用import导入所需的方法,成员。
import {foo, bar} from "dep";
文件名: dep.js
export foo function(){};
export const bar = 22
归功于Paul Shan。更多信息。
require
方法?
const {a,b} = require('module.js');
也可以正常工作...如果您出口,a
并且b
module.exports = { a: ()={}, b: 22 }
-@BananaAcid回应的第二部分
从现在开始,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
不知道为什么(可能是优化-延迟加载?)是否可以那样工作,但是我注意到,import
如果不使用导入的模块,可能无法解析代码。
在某些情况下,这可能不是预期的行为。
以讨厌的Foo类作为我们的示例依赖项。
foo.ts
export default class Foo {}
console.log('Foo loaded');
例如:
索引
import Foo from './foo'
// prints nothing
索引
const Foo = require('./foo').default;
// prints "Foo loaded"
索引
(async () => {
const FooPack = await import('./foo');
// prints "Foo loaded"
})();
另一方面:
索引
import Foo from './foo'
typeof Foo; // any use case
// prints "Foo loaded"
node --experimental-modules index.mjs
使您可以在import
没有Babel的情况下使用,并且可以在Node 8.5.0+中工作。您还可以(并且应该)将npm软件包发布为本地ESModule,并向后兼容旧require
方法。