在我正在合作的一个项目中,我们有两个选择可以使用哪个模块系统:

使用require导入模块,使用using module导出模块。Exports和Exports .foo。 使用ES6 import导入模块,使用ES6 export导出模块

使用其中一种是否有性能上的好处?如果我们要使用ES6模块而不是Node模块,还有什么我们应该知道的吗?


当前回答

您可能需要考虑以下几种用法/功能:

要求:

你可以动态加载加载的模块名不是 预定义的/静态的,或者你有条件地加载一个模块仅当 它是“真正需要的”(取决于特定的代码流)。 加载 同步的。这意味着如果你有多个需求,它们就是 一个接一个地装载和处理。

ES6进口:

你可以使用 命名导入可选择性地只加载您需要的部分。可以 节省内存。 导入可以是异步的(在当前的ES6 Module Loader中,它实际上是异步的),并且可以执行得更好一些。

同样,Require模块系统也不是基于标准的。现在ES6模块已经存在,它不太可能成为标准。在未来,在各种实现中会有对ES6模块的原生支持,这将在性能方面具有优势。

其他回答

不确定为什么(可能是优化-延迟加载?)它是这样工作的,但我注意到,如果导入的模块不使用,导入可能无法解析代码。 在某些情况下,这可能不是预期的行为。

以讨厌的Foo类为例。

foo.ts

export default class Foo {}
console.log('Foo loaded');

例如:

index.ts

import Foo from './foo'
// prints nothing

index.ts

const Foo = require('./foo').default;
// prints "Foo loaded"

index.ts

(async () => {
    const FooPack = await import('./foo');
    // prints "Foo loaded"
})();

另一方面:

index.ts

import Foo from './foo'
typeof Foo; // any use case
// prints "Foo loaded"

ES模块是静态的,这意味着导入是在每个模块的顶层描述的,并且在任何控制流语句之外。这是行不通的: If(条件){ 从'module1'导入module1 }

但是在commonjs中,它是允许的:

if (condition) {
    module = require('module1')
}

ES modules run implicitly in strict mode. This means that we don't have to explicitly add the "use strict" statements at the beginning of every file. Strict mode cannot be disabled; therefore, we cannot use undeclared variables or the with statement or have other features that are only available in non-strict mode. strict mode is a safer execution mode. In ESM, some important CommonJS references are not defined. These include require , exports , module.exports , __filename, and __dirname. We can import CommonJS modules from ESM by using the standard import syntax. But only default exports work: import packageName from 'commonjs-package' // Works import { moduleName } from 'commonjs-package' // Errors

但是,从CommonJS模块中导入ES模块是不可能的。

ESM不能直接将JSON文件作为模块导入,这个特性在CommonJS中使用非常频繁。这就是为什么在reactjs中使用fetch api。 从'./data导入数据。json / /失败

我个人使用import,因为我们可以通过import导入所需的方法和成员。

import {foo, bar} from "dep";

文件名:dep.js

export foo function(){};
export const bar = 22

这要归功于单霁翔。更多信息。

使用其中一种是否有性能上的好处?

目前的答案是否定的,因为目前没有一个浏览器引擎实现从ES6标准的导入/导出。

一些比较图表http://kangax.github.io/compat-table/es6/没有考虑到这一点,所以当你看到几乎所有的绿色Chrome,只是小心。没有考虑ES6中的import关键字。

换句话说,包括V8在内的当前浏览器引擎不能通过任何JavaScript指令从主JavaScript文件中导入新的JavaScript文件。

(在V8根据ES6规范实现之前,我们可能还会有几个bug或几年的时间。)

这个文件是我们需要的,这个文件是我们必须遵守的。

ES6标准说,模块依赖关系应该在我们读取模块之前就存在,就像在编程语言C中,我们有(headers) .h文件一样。

这是一个经过良好测试的结构,我相信创建ES6标准的专家们已经考虑到了这一点。

这使得Webpack或其他包捆绑器能够在某些特殊情况下优化包,并减少一些不需要的依赖包。但在完全依赖的情况下这永远不会发生。

导入/导出本地支持将需要一段时间,并且require关键字在很长一段时间内不会去任何地方。

需要什么?

这是node.js加载模块的方式。(https://github.com/nodejs/node)

Node使用系统级方法读取文件。在使用require时,你基本上依赖于它。require将在一些系统调用中结束,如uv_fs_open(取决于结束系统,Linux, Mac, Windows),以加载JavaScript文件/模块。

要检查这是否正确,请尝试使用Babel.js,您将看到import关键字将被转换为require。

当涉及到异步或延迟加载时,import()要强大得多。当我们以异步方式需要该组件时,我们会以某种异步方式使用import,例如在const变量中使用await。

const module = await import('./module.js');

或者如果你想使用require(),

const converter = require('./converter');

import()实际上在本质上是异步的。正如neehar venugopal在ReactConf中提到的,你可以使用它来动态加载客户端架构的react组件。

此外,当涉及到路由时,它是更好的方式。这是使网络日志在用户连接到特定网站时下载到其特定组件的一个特殊之处。例如,在仪表板之前的登录页面不会下载仪表板的所有组件。因为什么是需要当前即登录组件,这只会下载。

导出也一样:ES6的导出与CommonJS module.exports完全相同。

注:如果你正在开发一个node.js项目,那么你必须严格使用require(),因为如果你将使用import,节点将抛出异常错误作为无效的令牌'import'。所以node不支持import语句。

更新-根据Dan Dascalescu的建议:自v8.5.0(2017年9月发布)以来,node -experimental-modules索引。mjs让你不用Babel就可以使用import。你也可以(也应该)将你的npm包作为原生ESModule发布,并向后兼容旧的require方式。

在哪里使用异步导入,请参见https://www.youtube.com/watch?v=bb6RCrDaxhw