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

--format=cjs behave differently depends on node version #1636

Closed
zen0wu opened this issue Sep 26, 2021 · 5 comments
Closed

--format=cjs behave differently depends on node version #1636

zen0wu opened this issue Sep 26, 2021 · 5 comments

Comments

@zen0wu
Copy link

zen0wu commented Sep 26, 2021

Not sure if I configured incorrectly, but when we set target to different node version, the transform behavior on await import is different. I didn't find a way to configure target to node14 that keep the await import behavior to commonjs.

Sample code

import optimist from 'optimist';

async function f() {
  return await import('optimist');
}

f().then(o => {
  console.log('await import', optimist.parse);
  console.log('await import', o.parse);
})

Transform output

--target=node12

async function f() {
  return await Promise.resolve().then(() => __toModule(require("optimist")));
}

--target=node14

async function f() {
  return await import("optimist");
}

tsc output (module=commonjs, despite of node version)

async function f() {
  return await Promise.resolve().then(() => __importStar(require("optimist")));
}

Run output

❯ node_modules/.bin/esbuild --format=cjs --platform=node --target=node14 test.ts | volta run --node 14 node -
await import [Function: bound ]
await import undefined

❯ node_modules/.bin/esbuild --format=cjs --platform=node --target=node12 test.ts | volta run --node 12.21.0 node -
await import [Function: bound ]
await import [Function: bound ]
@hyrious
Copy link

hyrious commented Sep 27, 2021

Dynamic import is available in node13, so it is kept when the target node version is higher than that.
tsc actually does not have an option to specify target node version, it only has es versions like ES6 and ES2020.

To speak the difference of import() and require(), when the imported library is pure ESM (like the ones from Sindre Sorhus'), require() won't work. However import() works both for CJS and ESM inputs.

@zen0wu
Copy link
Author

zen0wu commented Sep 27, 2021

thanks for the context. I think it's just surprising to me that esbuild's output varies based on node version. Other tools like TSC exposes option like "module":"commonjs", and emits code that works with the option in any case.

I haven't looked into every piece of our internal code to see whether it's possible to migrate them to respect await import, but in the case it might be hard, we're stuck with target=node12 even if we want to upgrade to node 14.

@clydin
Copy link

clydin commented Sep 27, 2021

Native dynamic import expressions are critical to CommonJS/ESM interoperability. TypeScript’s (tsc) current behavior unfortunately breaks this interoperability.
To support ESM code use from CommonJS, Node.js considers dynamic import expressions as a supported part of the CommonJS module system (https://nodejs.org/api/esm.html#esm_import_expressions).

@evanw
Copy link
Owner

evanw commented Oct 17, 2021

See #1084 for additional context.

@zen0wu
Copy link
Author

zen0wu commented Oct 24, 2021

Thanks, I guess this is a won't fix, closing.

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

4 participants