一年多以来,我已经使用esm和std / esm软件包编写了我的所有代码,而无需babel,我能够无缝地将cjs依赖性软件包无缝使用。
现在在nodejs V14中提供了不带标志的esm / cjs混合支持,并且std / esm项目似乎即将结束,因此我认为我应该尝试迁移以查看可能的问题。好吧,我找到了。
https://github.com/standard-things/esm
https://nodejs.org/api/esm.html#esm_ecmascript_modules
我遇到的问题是,与std / esm不同,现在V14 nodejs中包含的esm / cjs支持打破了命名导入(我假设是commonjs模块导出),在std / esm上正常工作。
例如https://github.com/sindresorhus/make-dir/blob/978bee9186bf0c41640ed21567921daf8c303225/index.js#L106
as包使用cjs。这是出口
module.exports.sync = (input, options) => {
checkPath(input);
options = processOptions(options);
在我的package.json中使用"type":"module"
。我的代码中有导入import { sync as mkdir } from 'make-dir'
,使用std / esm 可以正常工作。但是在nodejs 14中使用它表示找不到命名的导出sync
。**
import { sync as mkdir } from 'make-dir'
^^^^
SyntaxError: The requested module 'make-dir' does not provide an export named 'sync'
我被困在这里吗?我需要呆在std / esm上吗? (但似乎项目已经结束)我不能/不应该使用
容纳cjs模块的整个代码库import mk from 'make-dir'
const mkdir = mk.sync
为使任何人都可以轻松创建它,我制作了一个回购协议,可以克隆并运行此差异
https://github.com/dkebler/core-esm-named-import-error
不管怎么说,v14中的esm将会取代使用std / esm的下降。显然不是:(。
答案 0 :(得分:4)
Node.js仅支持CJS脚本默认导出的技术原因是因为ESM import
是静态的(在模块执行之前已解析),而CJS module.exports
是动态的(您可以做一些疯狂的事情)像module.exports[Date.now()] = 0
并摆脱它)。唯一可以确定的是,确定CJS模块导出的“名称”是解析并执行它,这似乎与ES6规范不兼容。
某些捆绑程序(例如std / esm)在CJS模块代码上使用正则表达式来查找module.exports.<named export> =
的实例,并使用其为模块定义命名的导出列表。这种方法的缺点是您找不到所有导出,大型文件的解析可能会占用大量内存。同样,这意味着需要对CJS模块进行两次解析,尽管对于捆绑器而言,性能下降可能还不错,但对于像Node.js这样的运行时来说,却不值得。
那该怎么办?这是我遇到此问题时一直在做的事情: