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

Module dynamic imported from cjs output has unexpected exports. #3544

Closed
chenjun1011 opened this issue Dec 14, 2023 · 1 comment
Closed

Module dynamic imported from cjs output has unexpected exports. #3544

chenjun1011 opened this issue Dec 14, 2023 · 1 comment

Comments

@chenjun1011
Copy link

Minimal repro:

// a.js
exports.createElement = function() {
  console.log('createElement')
}

// index.mjs
import { createElement } from './a';

export async function renderToHTML(requestContext) {
  createElement();
}

Esbuild config:

import * as esbuild from 'esbuild'

await esbuild.build({
  entryPoints: ['index.mjs'],
  bundle: true,
  outfile: 'bundle.js',
  target: 'node12.20.0',
  format: 'cjs'
});

Outputted bundle.js:

// ...

// a.js
var require_a = __commonJS({
  "a.js"(exports) {
    exports.createElement = function() {
      console.log("createElement");
    };
  }
});

// index.mjs
var esbuild_demo_exports = {};
__export(esbuild_demo_exports, {
  renderToHTML: () => renderToHTML
});
module.exports = __toCommonJS(esbuild_demo_exports);
var import_a = __toESM(require_a(), 1);
async function renderToHTML(requestContext) {
  (0, import_a.createElement)();
}

When use 'import()' to dynamic load bundle.js

const mod = await import('./bundle.js');
console.log('mod=>', mod);

The module loaded has an unexpected export createElement.

image

It seems although the exports passed to the module a are not node.js's native exports, it still changed the native exports. This maybe a bug in dynamic import.(The problem only occurs in the case of dynamic import)

image

If esbuild can avoid the keyword exports in __commonJS function, or provide some overriding configuration
, may solved this problem.

@evanw
Copy link
Owner

evanw commented Dec 14, 2023

This is a bug in node. Node is trying to guess at what exports the module has and it's guessing wrong. If I rename exports to not_exports then the bug isn't triggered. Node isn't doing the correct scope analysis to determine whether exports is from the top-level module or a nested module. It just makes up an export called foo if it finds an assignment to exports.foo anywhere in the source code, even if exports is a local variable. I can try to have esbuild avoid naming variables exports when targeting node to work around this bug in node.

@evanw evanw closed this as completed in 109449e Dec 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants