主要观点:作者在 Node.js 中实现了对同步 ES 模块的实验性支持(require()
可加载同步 ES 模块),解释了为何该功能长期缺失及背后的原因,包括ERR_REQUIRE_ESM
带来的困扰、ESM 的同步性、Node.js 中的 ESM 孤岛问题、ESM 加载器的复杂性等,并阐述了后续工作,如处理边缘情况、支持自定义加载器钩子、处理入口点的顶级await
等。
关键信息:
- 多年来可
import cjs
但不能require(esm)
,ERR_REQUIRE_ESM
困扰众多,导致包作者需同时提供 CJS 和 ESM 版本。 - 最初认为
require()
不支持加载 ESM 是因为 ESM 异步执行,后发现 ESM 本身设计为有条件异步,require()
可支持无顶级await
的 ESM 图。 - 2019 年已有支持同步 ESM 图的提议但未成功,规范中基于语法的同步评估基础已在 2019 年确定,但在 Node.js 中未广泛知晓。
- Node.js 中 ESM 的开发过程存在 ESM 孤岛问题,导致关于同步
require(esm)
的讨论局限于特定群体,且 ESM 加载器的复杂性及引发的争议也阻碍了其发展。 - 去年重新开始讨论同步
require(esm)
,通过简单方式实现并提交 PR,目前仍为实验性功能,需处理边缘情况和支持自定义加载器钩子等。
重要细节:
- 作者多年贡献 Node.js,起初相信文档中关于
require()
不支持加载 ESM 的说法,后发现文档误导。 - 测试发现约 30 个 npm 上的高影响力纯 ESM 包无顶级
await
,支持同步模块可解决生态系统中的很多问题。 - ESM 加载器在 JavaScript 中实现,代码复杂,存在循环依赖、防御
TDZs
等问题,影响可读性和性能,部分性能测试显示同步require(esm)
更快。 - 目前
require(esm)
仅支持明确标记为 ESM 的模块,后续可实现 fallback 到 ESM 加载等功能。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。