一直以来 Node.js 中存在一个问题,CommonJS 与 ES Modules 如何更好的共存? 是令大多数 Node.js 开发者头疼的问题。
当在 ES Modules 模块中引入 CommonJS 模块代码,一切是 Ok 的。如下代码所示:
// c.jsmodule.exports = { moduleName: 'a'}
// m.mjsimport C_Module from './c.js'console.log(C_Module); // { moduleName: 'a' }
换一种方式,让 CommonJS 引入 ES Modules,如下代码所示:
// m.mjsexport default 'm'
// c.jsconst M_Module = require('./m.mjs')console.log(M_Module);
终端运行 node c.js,会得到如下提示
图片
ERR_REQUIRE_ESM 这个错误太熟悉不过了,它困惑了很多的 Node.js 开发者,为什么换个顺序就不行?
看到的很多答案是这样的 “不支持使用 require 加载 ES 模块,因为 ES 模块是异步执行的”,后面大家就默认了 “CommonJS 是同步,ES Modules 是异步” 这样的一个规则。
CommonJS 模块如何加载 ES Modules 模块,这个问题 2019 年就已经提出,参考 “Support requiring .mjs files” https://github.com/nodejs/node/pull/30891 这个问题在当时没有被解决。
图片
ES Modules 在文件顶层可以使用 Top-Level Await,该方法看之前的介绍,是在使用 esm 加载器加载的 .mjs 文件上使用 require 的功能时,使用了与 esm Top-Level Await 相同的权衡。
这意味着:如果可能,所有执行和评估都是同步进行的,通过立即展开执行的组件承诺。这意味着任何现有的代码都不应该有可观察到的行为变化,因为到目前为止还不存在任何异步模块。问题在于,一旦使用需要异步执行的模块,它必须让出事件循环来执行该操作,这反过来又允许其他代码在异步操作之后的继续执行之前执行,这对于现在变成了异步模块的调用者是可观察到的。如果这对你的调用者很重要,那么意味着将你的模块执行异步化可能被视为库的破坏性更改,但实际上,对于大多数调用者来说,这并不重要。而且,由于当前的生态系统,零个模块是异步执行的,因此在有异步执行的模块之前,这种方法没有任何缺点,因为没有执行会改变人们今天所期望的(当然,除了不再错误地要求("./foo.mjs"))。
最后,问题被关闭了,原因是 “因为纯粹从技术角度来看,目前尝试在事件循环已经运行时旋转它是行不通的”。
图片
问题是挺错综复杂的,感兴趣的可以去看看 2019 年提出的这个 Issue。
2019 ~ 2024 这一令大多数开发者头疼的问题,由 Node.js 的维护者成员 “Joyee Cheung” 再次提出了解决方案。参考 Issue “module: support require()ing synchronous ESM graphs” https://github.com/nodejs/node/pull/51977
图片
参考 Joyee Cheung 博客的介绍 https://joyeecheung.github.io/blog/2024/03/18/require-esm-in-node-js/
图片
去年年底左右,Joyee Cheung 发现了 ESM 的求值可以基于语法同步,而只是 Node.js 将异步性扔到加载过程中后,便与 @GeoffreyBooth 开始讨论重新启动同步 require(esm)。
因此,才有了这个 PR。与 2019 年的 PR 相比主要区别在于它试图将 require(esm) 的范围保持小型,并且仅支持加载同步 ESM。
后续会通过 --experimental-require-module 标志启用,则加载的 ECMAScript 模块 require() 时要满足以下要求:
有网友就在下面问了,这能向后移至到 Node.js 18? 大家还是很喜欢这个功能的!Node.js v20 可能还有希望,这要取决于 Node.js 的发布团队,期待下个 Node.js 版本!
图片
这一问题的解决对 Node.js 模块来讲是里程碑式的,很敬佩 Joyee Cheung 的才华!
本文链接:http://www.28at.com/showinfo-26-79450-0.html一个提出五年的 Node.js 模块问题,终被解决!
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 我们一起聊聊如何向文本添加渐变效果和图案