CommonJS 命名导出什么时候可以被 ES 模块导入?

GOT*_*O 0 12 javascript commonjs node.js es6-modules module-export

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

es.mjs

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

console.log(MyNamedExport);
Run Code Online (Sandbox Code Playgroud)

commonjs.cjs(不错)

exports.MyNamedExport = 'OK';
Run Code Online (Sandbox Code Playgroud)

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

> node ./es.mjs
OK
Run Code Online (Sandbox Code Playgroud)

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

commonjs.cjs(不好的)

> node ./es.mjs
OK
Run Code Online (Sandbox Code Playgroud)
> 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)

Run Code Online (Sandbox Code Playgroud)

当然,当我的 CommonJS 命名导出被另一个 CommonJS 模块导入时,括号没有任何区别。

为什么会发生这种情况?

当我编写 CommonJS 模块以确保命名导出可以被 ES 模块导入时,我应该怎么做?

Ber*_*rgi 8

来自文档

\n
\n

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

\n

[\xe2\x80\xa6]

\n

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

\n

命名导出检测涵盖许多常见的导出模式、重新导出\n模式以及构建工具和转译器输出。请参阅cjs-module-lexer\n了解所实现的确切语义。

\n
\n