什么时候可以通过 ES 模块导入名为 export 的 CommonJS?

问题描述

我有一个 ES 模块,它使用我编写的 Commonjs 模块的命名导出。

es.mjs

import { MyNamedExport } from './commonjs.cjs';

console.log(MyNamedExport);

commonjs.cjs(不错的)

exports.MyNamedExport = 'OK';

当我像这样在 Node.js 中运行 ES 模块时,一切都很好。

> node ./es.mjs
OK

无论如何,如果 Commonjs 模块中的导出部分以某种看似无关的方式进行了更改,即通过添加一对括号,命名导出将停止工作。

commonjs.cjs(坏的)

(exports).MyNamedExport = 'OK';
> node ./es.mjs
file:///path/to/current/folder/es.mjs:1
import { MyNamedExport } from './commonjs.cjs';
         ^^^^^^^^^^^^^
SyntaxError: Named export 'MyNamedExport' not found. The requested module './commonjs.cjs' is a Commonjs module,which may not support all module.exports as named exports.
Commonjs modules can always be imported via the default export,for example using:

import pkg from './commonjs.cjs';
const { MyNamedExport } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:104:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:149:5)
    at async Loader.import (node:internal/modules/esm/loader:166:24)
    at async Object.loadESM (node:internal/process/esm_loader:68:5)

当然,当我的名为 export 的 Commonjs 被另一个 Commonjs 模块导入时,括号没有区别。

为什么会这样?

一个Commonjs模块的时候应该怎么做才能保证命名的exports可以被ES模块导入?

解决方法

来自the docs

为了更好地兼容 JS 生态系统中的现有用法, Node.js 另外[到默认导入] 尝试确定名为导出的 CommonJS 每个导入的 CommonJS 模块都将它们作为单独的 ES 提供 使用静态分析过程导出模块。

[…]

命名导出的检测基于常见的语法模式,但 并不总是正确检测命名导出。在这些情况下,使用 上面描述的默认导入表单可能是更好的选择。

命名出口检测涵盖了许多常见的出口模式,再出口 模式和构建工具和转译器输出。见cjs-module-lexer 对于实现的确切语义。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...