Node.js 计划支持 import/export ES6 (ECMAScript 2015) 模块

Node.js plans to support import/export ES6 (ECMAScript 2015) modules

我在网上找遍了都没有一个明确的答案。

目前 Node.js 仅使用 CommonJS 语法加载模块,如果你真的想使用标准的 ECMAScript 2015 模块语法,你要么必须事先转译它,要么使用外部模块加载器在运行时。

目前我不太愿意使用这两种方法中的任何一种,Node.js 维护者甚至计划支持 ECMAScript 2015 模块吗?我还没有找到任何关于这个的提示。

目前 Node.js 6.x 声称支持 96% 的 ECMAScript 2015 功能,但没有任何模块参考 (Node.js ECMAScript 2015 support link)。

您知道 Node.js 是否会在不久的将来开箱即用地支持这些模块吗?

Node.js 13.2.0 及以上

Node.js 13.2.0 现在支持没有标志的 ES 模块。但是,该实现仍被标记为实验性的,因此在生产中谨慎使用。

要在 13.2.0 中启用 ECMAScript 模块 (ESM) 支持,请将以下内容添加到您的 package.json

{
  "type": "module"
}

所有 .js.mjs(或没有扩展名的文件)都将被视为 ESM。

除了整个 package.json opt-in,还有许多不同的选项,所有这些都在 documentation for 13.2.0.

中有详细说明

Node.js 13.1.0 及以下

那些仍在使用旧版本 Node 的人可能想尝试 [esm][3] 模块加载器,它是 Node.js 的 ES 模块规范的 production-ready 实现:

node -r esm main.js

详细更新...

2019 年 4 月 23 日

最近发布了一项 PR,以更改检测 ECMAScript 模块的方式: https://github.com/nodejs/node/pull/26745

它仍然落后于 --experimental-modules 标志,但加载模块的方式有重大变化:

  • package.type 可以是 modulecommonjs
    • type: "commonjs":
      • .js 被解析为 CommonJS
      • 没有扩展名的默认入口点是 CommonJS
    • type: "module":
      • .js 被解析为 ECMAScript 模块
      • 默认不支持加载JSON或原生模块
      • 没有扩展的默认入口点是 ECMAScript 模块
  • --type=[mode] 让您设置入口点的类型。将覆盖入口点 package.type
  • 一个新的文件扩展名 .cjs
    • 这是专门为了支持在module模式下导入CommonJS。
    • 这仅在 ECMAScript 模块加载器中,CommonJS 加载器保持不变,但如果您使用完整文件路径,扩展将在旧加载器中工作。
  • --es-module-specifier-resolution=[type]
    • 选项是 explicit(默认)和 node
    • 默认情况下,我们的加载器不允许在导入中使用可选扩展,如果有扩展,模块的路径必须包含扩展
    • 默认情况下,我们的加载程序不允许导入具有索引文件的目录
    • 开发者可以使用--es-module-specifier-resolution=node启用CommonJS说明符解析算法
    • 这不是一个“功能”,而是一个实验性的实现。预计在 flag 被移除之前会发生变化
  • --experimental-json-loader
    • "type": "module"
    • 时导入 JSON 的唯一方法
    • 启用所有 import 'thing.json' 时将独立于模式
    • 通过实验加载程序
    • 基于whatwg/html#4315
  • 您可以使用 package.main 设置模块的入口点
    • main 中使用的文件扩展名将根据模块的类型进行解析

2019 年 1 月 17 日

Node.js 11.6.0 仍然将 ES 模块列为实验性的,在标志后面。

2017 年 9 月 13 日

Node.js 8.5.0 已发布,支持标志后面的 mjs 文件:

node --experimental-modules index.mjs

此计划是删除 v10.0 LTS 版本的标志。

--信息过时。出于历史目的保留在这里--

2017 年 9 月 8 日

Node.js master 分支已更新,初步支持 ESM 模块: https://github.com/nodejs/node/commit/c8a389e19f172edbada83f59944cad7cc802d9d5

这应该在最近的每晚可用(这可以是 installed via nvm 到 运行 以及您现有的安装): https://nodejs.org/download/nightly/

并在 --experimental-modules 标志后面启用:

package.json

{
  "name": "testing-mjs",
  "version": "1.0.0",
  "description": "",
  "main": "index.mjs" <-- Set this to be an mjs file
}

然后运行:

node --experimental-modules .

2017 年 2 月:

An Update on ES6 Modules in Node.js

Node.js 伙计们决定 最不坏的 解决方案是使用 .mjs 文件扩展名。从中得出的结论是:

In other words, given two files foo.js and bar.mjs , using import * from 'foo' will treat foo.js as CommonJS while import * from 'bar' will treat bar.mjs as an ES6 Module

至于时间表...

At the current point in time, there are still a number of specification and implementation issues that need to happen on the ES6 and Virtual Machine side of things before Node.js can even begin working up a supportable implementation of ES6 modules. Work is in progress but it is going to take some time — We’re currently looking at around a year at least.

2016 年 10 月:

Node.js 上的一位开发人员最近参加了 TC-39 会议并写了一篇关于要为 Node.js 实施的拦截器的精彩文章:

Node.js, TC-39, and Modules

基本take-away由此得出:

  • 静态分析 ECMAScript 模块,评估 CommonJS
  • CommonJS 模块允许 monkey-patching 导出,而 ECMAScript 模块目前不允许
  • 如果没有某种形式的用户输入,很难检测什么是 ECMAScript 模块和什么是 CommonJS,但他们正在尝试。
  • *.mjs 似乎是最有可能的解决方案,除非他们可以在没有 user-input
  • 的情况下准确地检测到 ECMAScript 模块

--原答案--

这一段时间以来一直是个烫手山芋。底线是,Node.js 最终会支持ES2015 syntax for importing/exporting modules - most likely when the specification for loading modules 已最终确定并达成一致。

这是 a good overview 的原因 Node.js。从本质上讲,他们需要确保新规范适用于主要是条件同步加载的 Node.js 以及主要是异步加载的 HTML。

现在没有人确切知道,但我想 Node.js 将支持 import/export 静态加载,除了新的 System.import 动态加载 - 同时仍然保持 require 用于遗留代码。

这里有一些关于 Node 如何实现这一点的建议: