Node.js 计划支持导入/导出 ES6 (ECMAScript 2015) module

IT技术 javascript node.js module ecmascript-6 es6-modules
2021-01-20 05:19:42

我一直在寻找互联网上的所有内容,但没有明确的答案。

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

目前我对使用这两种方法中的任何一种都不太积极,Node.js 维护者是否甚至计划支持 ECMAScript 2015 module?我完全没有找到任何关于此的提示。

目前,Node.js 6.x 声称支持 96% 的 ECMAScript 2015 功能,但没有任何对module的引用(Node.js ECMAScript 2015 支持链接)。

您知道 Node.js 是否会在不久的将来立即支持这些module?

1个回答

Node.js 13.2.0 及以上

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

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

{
  "type": "module"
}

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

除了完全package.json选择加入之外,还有许多不同的选项,所有这些都在13.2.0文档中进行了详细说明

Node.js 13.1.0 及以下

那些仍在使用旧版本 Node 的人可能想尝试[esm][3]module加载器,它是 Node.js 的 ES module规范的生产就绪实现:

node -r esm main.js

详细更新...

2019 年 4 月 23 日

一个 PR 最近登陆以改变检测 ECMAScript module的方式:https : //github.com/nodejs/node/pull/26745

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

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

2019 年 1 月 17 日

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

2017 年 9 月 13 日

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

node --experimental-modules index.mjs

这样做的计划是删除 v10.0 LTS 版本的标志。

——过时的信息。留在这里是为了历史目的——

2017 年 9 月 8 日

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

这应该在最新的每晚可用(这可以通过 nvm 安装以与现有安装一起运行):https : //nodejs.org/download/nightly/

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

包.json

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

然后运行:

node --experimental-modules .

2017 年 2 月:

Node.js 中 ES6 module的更新

Node.js 人员已经决定,最不坏的解决方案是使用.mjs文件扩展名。从中得出的结论是:

换句话说,给定两个文件foo.jsand bar.mjs, usingimport * from 'foo'foo.js视为 CommonJS 而import * from 'bar'bar.mjs视为 ES6 Module

至于时间线...

目前,在 Node.js 甚至可以开始研究 ES6 module的可支持实现之前,ES6 和虚拟机方面仍有许多规范和实现问题需要解决。工作正在进行中,但需要一些时间——我们目前至少在一年左右

2016 年 10 月:

Node.js 的一位开发人员最近参加了 TC-39 会议,并写了一篇关于 Node.js 实现的阻塞器的精彩文章:

Node.js、TC-39 和module

基本的结论是:

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

——原答案——

一段时间以来,这一直是一个烫手山芋。底线是,是的,Node.js 最终将支持ES2015导入/导出module的语法——最有可能是在最终确定并商定加载module规范时。

这里很好地概述了是什么阻碍了 Node.js。本质上,他们需要确保新规范适用于 Node.js,Node.js 主要是有条件的同步加载,也适用于主要是异步的 HTML。

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

下面是一些关于 Node 如何实现这一目标的建议:

关于.mjs扩展名:We have affectionately called these “Michael Jackson Script” files in the past. 以防万一您在 JS 演讲中听到有人谈论流行艺术家。
2021-03-12 05:19:42
@Mikhail 这只是重命名文件。此外,import dependency from "./file"如果文件是file.mjs. 大多数module开发人员最终会迁移到 ESModules,因为它们提供了一些重要的好处。
2021-03-12 05:19:42
我不明白为什么更改导入语法还不够。一种用于导入 es(“正确”)的语法和一种用于导入 cjs 的语法?换句话说,给定两个文件 foo.js 和 bar.js , import * from 'foo'将 foo.js 视为 CommonJS import * as bar from 'bar'将 bar.js 视为 ES6 Module 谁能解释一下?
2021-03-18 05:19:42
需要明确的是,这不是“我的”提议,我正在复制typescript已经在做的事情。要回答您的问题,您可以使用“bar”访问导出: bar.foobar() import {foo as Foo} from “./foo” 是识别 ES6 module的机制。var Foo = require(“./foo”) 是识别 CJS module的机制。在 Typescript 中,commonjs 输出如下所示: var mod1_1 = require("./mod1"); 出口.mod1 = mod1; ES6 输出如下所示: import { mod1 } from “./mod1”; 导出 { mod1 }
2021-03-18 05:19:42
@CoreyAlix 语法通常不会为了支持环境而改变。毕竟这真的只会影响 Node。此外,语法有点不直观。我如何访问您建议的语法中的导出?
2021-04-01 05:19:42