在 Node.js 中要求(esm)

主要观点:作者在 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 加载等功能。
阅读 14
0 条评论