简体   繁体   中英

When can a CommonJS named export be imported by an ES module?

I have an ES module that uses a named export from a CommonJS module that I authored.

es.mjs

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

console.log(MyNamedExport);

commonjs.cjs (good one)

exports.MyNamedExport = 'OK';

When I run the ES module in Node.js like this everything is fine.

> node ./es.mjs
OK

Anyway, if the export part in the CommonJS module is changed in some seemingly irrelevant way, ie by adding a pair of parentheses, the named export stops working.

commonjs.cjs (bad one)

(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)

Of course, when my CommonJS named export is imported by another CommonJS module, the parentheses make no difference.

Why is this happening?

What should I do when I write a CommonJS module to make sure that named exports can be imported by ES modules?

From the docs :

For better compatibility with existing usage in the JS ecosystem, Node.js in addition [to the default import] attempts to determine the CommonJS named exports of every imported CommonJS module to provide them as separate ES module exports using a static analysis process.

[…]

The detection of named exports is based on common syntax patterns but does not always correctly detect named exports. In these cases, using the default import form described above can be a better option.

Named exports detection covers many common export patterns, reexport patterns and build tool and transpiler outputs. Seecjs-module-lexer for the exact semantics implemented.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM