在节点V14中从std / esm迁移到esm支持-找不到命名的导入-在std / esm上工作正常

时间:2020-05-29 15:00:08

标签: node.js node-modules es6-modules

一年多以来,我已经使用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的下降。显然不是:(。

1 个答案:

答案 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这样的运行时来说,却不值得。

那该怎么办?这是我遇到此问题时一直在做的事情: