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

Fix ESM exports #78

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

remcohaszing
Copy link

@remcohaszing remcohaszing commented Aug 21, 2023

This uses the package.json exports field to support native ESM. The module field is redundant and can even lead to compatibility issues, so it was removed.

TypeScript project references are used for building the project with two different settings. An additional package.json is written to mark the ESM output as actual ESM. Since ESM requires file extensions, those were added to all imports.

Mocha has been reconfigured to run tests for both CJS and ESM.

Also ESLint has been configured to lint all files in the repo, not just a shell specific glob pattern. As a result, this change contains some small ESLint fixes.

Closes #56
Closes #57

@graham-atom
Copy link

any idea on when this will merge?

@Yokozuna59
Copy link

Is there any updates on this PR? The workaround stated in #57 for esbuild build:

{
  // ...
  mainFields: ["module", "main"]
}

broke other parts, so the only way to resolve such error would be with this approach.

This uses the `package.json` `exports` field to support native ESM. The
`module` field is redundant and can even lead to compatibility issues,
so it was removed.

TypeScript project references are used for building the project with two
different settings. An additional `package.json` is written to mark the
ESM output as actual ESM. Since ESM requires file extensions, those were
added to all imports.

Mocha has been reconfigured to run tests for both CJS and ESM.

Also ESLint has been configured to lint all files in the repo, not just
a shell specific glob pattern. As a result, this change contains some
small ESLint fixes.
@remcohaszing
Copy link
Author

I rebased and added the module export condition, like in microsoft/vscode-languageserver-node#1386

@remcohaszing
Copy link
Author

This is also blocking some downstream issues mentioned in microsoft/vscode#192144

@afonsojramos
Copy link

Hi @aeschli, who needs to review this?

@aeschli
Copy link
Contributor

aeschli commented Jun 24, 2024

I added an exports section with #90

@remcohaszing
Copy link
Author

That PR:

  • Didn’t add .js extensions to relative imports, breaking usage from ESM
  • Points the import condition to a .js file with a package.json that doesn’t specify "type": "module" (faux ESM), breaking usage from ESM.
  • Only has CJS type definitions, which probably works, but is technically incorrect.

The latest version on npm is now broken.

$ cat package.json
{
  "dependencies": {
    "jsonc-parser": "3.3.0"
  }
}
$ node asd.mjs      
(node:134587) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/home/remco/Projects/test/node_modules/jsonc-parser/lib/esm/main.js:6
import * as formatter from './impl/format';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (node:internal/modules/cjs/loader:1376:18)
    at Module._compile (node:internal/modules/cjs/loader:1405:20)
    at Module._extensions..js (node:internal/modules/cjs/loader:1544:10)
    at Module.load (node:internal/modules/cjs/loader:1275:32)
    at Module._load (node:internal/modules/cjs/loader:1091:12)
    at wrapModuleLoad (node:internal/modules/cjs/loader:212:19)
    at cjsLoader (node:internal/modules/esm/translators:318:5)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:258:7)
    at ModuleJob.run (node:internal/modules/esm/module_job:262:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:474:24)

Node.js v22.3.0

"exports": {
".": {
"import": "./lib/esm/main.js",
"module": "./lib/esm/main.js",
Copy link

@xiaoxiangmoe xiaoxiangmoe Jun 25, 2024

Choose a reason for hiding this comment

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

What's the meaning of "module" exports?
I didn't see it in nodejs docs and webpack docs. Where is it used for or where is the official doc for it?

Copy link
Author

Choose a reason for hiding this comment

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

It tells bundlers to use it, even when the module is required from a CJS file. So it helps reduce bundle size and avoid the dual package hazard.

Choose a reason for hiding this comment

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

But the "import" condition is more widely used in webpack, vite and node. Why should we add unofficial "module" condition.

"compile": "tsc -p ./src && npm run lint",
"compile-esm": "tsc -p ./src/tsconfig.esm.json",
"prepack": "npm run clean && npm run test && npm run remove-sourcemap-refs",
"compile": "tsc -b && node ./build/fix-esm.mjs && npm run lint",
"remove-sourcemap-refs": "node ./build/remove-sourcemap-refs.js",

Choose a reason for hiding this comment

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

It seems that remove-sourcemap-refs job is useless. We can set "sourceMap": false in tsconfig. @aeschli

Copy link
Author

Choose a reason for hiding this comment

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

That breaks code coverage and source mapping when running tests.

@adrian-gierakowski
Copy link

anything still blocking this?

@afonsojramos
Copy link

@aeschli please note the issues referenced above

@aeschli
Copy link
Contributor

aeschli commented Aug 14, 2024

The PR removes the AMD/UMD support. Until now I was hesitating to do that as the Monaco editor still uses AMD for its development setup.
It looks like the Monaco editor team is now ok that we remove the AMD support.

  • We can go one step further and only publish ESM. Is that still too early?
  • We need to create new major version for the API breakage

@remcohaszing
Copy link
Author

Personally I would love to go ESM-only. I even advocate for it. But that would definitely be a breaking change.

This affects more than just the VSCode ecosystem. I suggest to discuss the impact with the team internally. Perhaps @jakebailey also has an opinion on this.

I’ll gladly update this PR accordingly

@jakebailey
Copy link
Member

There are other alternative packaging tools which would retain the other formats. I sort of suspect that someone's loading UMD in the browser or something, though I'm not sure how to determine that.

If you go ESM only, just please do so in a major bump. Other breaking changes have happened in minor bumps and have been frustrating to work with, but dropping whole module formats would be extra breaky.

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

Successfully merging this pull request may close these issues.

difficulty bundling with esbuild
8 participants