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

Expand info on module condition and dual package hazard #40

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions src/content/api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3665,17 +3665,17 @@ body:

- p: >
The following condition is also automatically included when the [platform](#platform)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that especially the change to mention neutral platform here is especially important because otherwise this could be misread by other implementers.

is set to either `browser` or `node` and no custom conditions are
configured. If there are any custom conditions configured (even an empty
list) then this condition will no longer be automatically included:
is not set to `neutral` and no custom conditions are configured. If there are any
custom conditions configured (even an empty list) then this condition will no longer
be automatically included:

- ul:
- >
`module`
<p>
This condition can be used to tell esbuild to pick the ESM variant for a
given import path to provide better tree-shaking when bundling. This
condition is not active when you run your code natively in node. It is
This condition can be used to tell esbuild to always pick the ESM variant for a
given import/require path to avoid dual package hazard and provide better tree-shaking when bundling.
This condition is not active when you run your code natively in node. It is
specific to bundlers, and originated from Webpack.
</p>

Expand Down Expand Up @@ -3705,6 +3705,13 @@ body:
that can work with node because node deliberately doesn't implement loading
ESM using `require`.

- p: >
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have also found out that to improve code portability between bundlers etc we are forced to structure things like this when the default export is involved:

// dist/pkg.mjs
export * from "./pkg.cjs.js";
export { _default as default } from "./pkg.cjs.default.js";

// dist/pkg.cjs.default.js
exports._default = require('./pkg.cjs.js').default

// dist/pkg.cjs.js
/*
  transpiled CJS content of the package with all named exports and named default
  don't try to avoid `.default` here
*/

The same problem spills into TS declarations:

// dist/pkg.d.mts
export * from "./index.js"; // yes, we are in the declaration file but we are using .js extension here
export { _default as default } from "./pkg.cjs.default.js";

// dist/pkg.cjs.default.d.ts
export { default as _default } from "./index.js"

// dist/index.d.ts
/*
  actual type declarations produced by TS
*/

I'm not sure if you want to include any of this in your docs though. It gets a little bit crazy and I wish that we wouldn't have to do those steps but here we are.

Note that when using `module` condition and falling back to CJS in node,
it's still advised to use the mentioned ESM wrapper that reexports CJS code
with `import` condition. This way you might make sure that `default` export
remains what you expect it to be or that it exists at all. Without that your
CJS module will always be importable in node with `import nsObject from 'pkg'`.

- h3: External

- p: >
Expand Down