Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js require(esm) and __esModule #16441

Open
nicolo-ribaudo opened this issue Apr 23, 2024 · 0 comments
Open

Node.js require(esm) and __esModule #16441

nicolo-ribaudo opened this issue Apr 23, 2024 · 0 comments

Comments

@nicolo-ribaudo
Copy link
Member

nicolo-ribaudo commented Apr 23, 2024

This issue is meant to be a place for tools maintainers to discuss about interop with Node.js

Node.js has experimental support for require(esm), and on its result does not set __esModule: true. How does this affect transpilers?

Consider this example:

// main.cjs

// This file was authored as ESM and compiled to CJS
//
// import x from "dep";
// console.log(x);

function _interopRequireDefault(mod) { return mod?.__esModule ? mod.default : mod }
const _dep = _interopRequireDefault(require("dep"));

console.log(_dep.default);
// dep

// This file was authored as ESM and compiled to CJS
// export default 2;
// export const named = 3;

exports.__esModule = true;
exports.default = 2;
exports.named = 3;

It currently logs 2. If dep starts publishing as native ESM, the "_interopRequireDefault" logic will not detect it anymore as "was ESM" and thus it will log { default: 2, named: 3 }. The author of main.cjs will have to rewrite their code:

// main.cjs

// This file was authored as ESM and compiled to CJS
//
// import x from "dep";
// console.log(x.default);

function _interopRequireDefault(mod) { return mod?.__esModule ? mod.default : mod }
const _dep = _interopRequireDefault(require("dep"));

console.log(_dep.default.default);

There are two ways to make the "stop compiling to CJS" change non-breaking for its consumers (assuming that they are on a Node.js version where require(esm) works):

  1. either Node.js adds __esModule: true on the result of require(esm)
  2. or all tools update their "was ESM" detection to return mod?.__esModule || mod?.[Symbol.toStringTag] === "Module" ? mod.default : mod

I originally pushed for (1), which is implemented in an open PR in the Node.js repo (52166), but as you can see in that PR it comes with problems. Maybe we could do (2) instead?

I'm opening this issue in the Babel repo as a place to discuss outside of the Node.js repo, so that we (tools) can give a unified opinion on whether Node.js should or shouldn't do (1).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants