Node.js中ECMAScript模块(ESM)的当前支持状态:
10月,模块小组发布了“新模块实施计划” 。 这篇文章解释了其中包含的内容。
相数
该过程分为三个阶段:
- 阶段1:创建“最小”核心-最小和确定的基本规则和功能集。
- 从第2阶段开始:基于内核创建更复杂的功能。
最低限度的核心将是未来工作的基础。 一旦获得类似的功能,新设计还将取代当前的实验性实施。
阶段1:Node.js中对核心ESM的最低支持
简化模块标识符
Modules Team的目标之一是实现“浏览器对等” :Node.js应该尽可能靠近浏览器。 内核通过简化模块标识符(指向模块的URL)的解析来实现:
- 每个模块标识符必须以带有扩展名的文件名结尾。 那是
- 扩展名不会自动添加
- 不支持导入目录(通过重定向到
dir/index.mjs
或读取package.json
的main
字段)。
- ES模块可以导入内置的Node.js模块(
path
等)。 它们是先前规则的唯一例外。 - 默认情况下,仅
.mjs
扩展名为.mjs
文件(如果您对其他扩展名的状态感兴趣,请参阅第2阶段)。 因此,其他类型的模块无法通过import
:CommonJS模块,JSON文件,本机模块。
将CommonJS基本功能引入ES模块
相容性
import {createRequireFromPath as createRequire} from 'module'; import {fileURLToPath as fromPath} from 'url'; const require = createRequire(fromPath(import.meta.url)); const cjsModule = require('./cjs-module.js');
- CommonJS模块将能够通过
import()
加载ES模块。
第二阶段和未来计划
- 在第二阶段,我们正在等待:
- 支持“裸”标识符,例如
'lodash'
。 最有可能的是,这将包括将这些标识符映射到真实路径的某种方式。 - 支持
.mjs
以外的其他文件扩展名。 其中包括对.js
文件中ES模块的支持。
- 第3阶段很可能将重点放在具有扩展点的模块加载器上,用户可以在其中插入其逻辑。
什么时候可以在Node.js中使用ES模块?
- 旗帜后面: 现在可用
- 警告:该行为与第1阶段中所述的行为不符(从Node.js 11.5.0开始)
- 在没有标志的情况下,并且按照阶段1:模块团队正在尝试尽快实现这一点。 我们希望这些模块将在Node.js 14(2020年4月)下的标记下释放,并尽可能移植到以前的版本中。
常见问题
- 为什么需要新的
.mjs
文件.mjs
?
- 区分ESM和CommonJS格式的每个决定都有其优点和缺点。 使用单独的分辨率似乎是一个不错的选择( 更多信息 )。
- 为什么Node.js的行为应类似于浏览器?
- 因为这使得重用代码成为可能。 例如,创建在浏览器和Node.js中都可以使用的库
- 这也应该有助于在编码期间在后端和前端之间进行切换。
- 为什么所有这些限制都是为了兼容性?
- ES和CommonJS模块在结构(静态与动态)和加载方式(异步与同步)之间存在很大差异。 约束有助于使事情变得简单-从长远来看,绝大部分将是ES模块。
- 为什么一切持续这么久?
- 这里涉及许多利益相关者,涉及许多不同的平台(Node.js,npm,浏览器,JS引擎,TypeScript,TC39等)。 如果我们真的得到了可以在任何地方使用的ES模块,恕我直言,值得等待。
感激之情
感谢Miles Borins对本文的反馈。
其他资料供进一步阅读