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

Barrel files (containing only exports) are considered CommonJS #2164

Closed
zofiag opened this issue Apr 7, 2022 · 3 comments
Closed

Barrel files (containing only exports) are considered CommonJS #2164

zofiag opened this issue Apr 7, 2022 · 3 comments
Labels

Comments

@zofiag
Copy link

zofiag commented Apr 7, 2022

Background

There's a common pattern to point main or module to a barrel file, which contains exports from other files.
An example dependency @aws-sdk/client-s3 has a module entry which points to es module version of their code. This file contains only export * entries. Even though it's an es modules version, Node still treats it as a CommonJS and throws an error.

Reproduction repository

https://github.com/zofiag/esm
node version: 16.14.2

npm install
npm run run

Expected result:
No errors, node can run built files (dist/index.js).

Actual result:
node_modules/@aws-sdk/client-s3/dist-es/index.js is considered CommonJS even though it is not. That file contains export * entries that point to other es modules files.

file:///.../esm/dist/index.js:2
import { S3Client } from "../node_modules/@aws-sdk/client-s3/dist-es/index.js";
         ^^^^^^^^
SyntaxError: Named export 'S3Client' not found. The requested module '../node_modules/@aws-sdk/client-s3/dist-es/index.js' 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 '../node_modules/@aws-sdk/client-s3/dist-es/index.js';
const { S3Client } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:127:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:191:5)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:337:24)
    at async loadESM (node:internal/process/esm_loader:88:5)
    at async handleMainPromise (node:internal/modules/run_main:61:12)
Error - exit Error: exit code 1
    at ChildProcess.<anonymous> (file:///.../esm/build.js:35:37)
    at ChildProcess.emit (node:events:520:28)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:291:12)

Notes

It seems to be more of a Node issue, but I couldn't find any useful info about it. Hope someone can help!

@evanw
Copy link
Owner

evanw commented Apr 7, 2022

I believe the interpretation as CommonJS may be due to the use of external: ["./node_modules/*"]. I was able to get your code to work by making @aws-sdk/client-s3 external explicitly. See also #1958. I'm planning to try fixing this in the next breaking change release by changing the --external feature to no longer rewrite external paths. I haven't made this change yet because it's a breaking change.

@evanw evanw added the breaking label Apr 7, 2022
@zofiag
Copy link
Author

zofiag commented Apr 8, 2022

Thanks for the answer!
I did try making @aws-sdk/client-s3 external explicitly and then dist/index.js is basically the same as index.js file. Which means that if I then run node index.js or node dist/index.js the CommonJS version of @aws-sdk/client-s3 is used instead of the esm one (@aws-sdk/client-s3/package.json has main pointing to CommonJS version).

  "main": "./dist-cjs/index.js",
  "types": "./dist-types/index.d.ts",
  "module": "./dist-es/index.js",

Using CommonJS version doesn't throw any errors. But if we enforce using esm version then we end up with the error I posted originally (SyntaxError: Named export 'S3Client' not found. The requested module '../node_modules/@aws-sdk/client-s3/dist-es/index.js' is a CommonJS module...).

Do you know a way of making esbuild/nodeuse esm version of a dependency (module entry from package.json) without throwing the above error?

@ShravanSunder
Copy link

ShravanSunder commented May 31, 2022

I believe the interpretation as CommonJS may be due to the use of external: ["./node_modules/*"]. I was able to get your code to work by making @aws-sdk/client-s3 external explicitly. See also #1958. I'm planning to try fixing this in the next breaking change release by changing the --external feature to no longer rewrite external paths. I haven't made this change yet because it's a breaking change.

@evanw how does external make the modules load as commonjs? i'm trying to make a esm module with esbuild. When using this module in an app, it is trying to load dependent modules as commonjs.

is there any temporary workaround for this?

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

No branches or pull requests

3 participants