fix: node+browser compatible ES module import paths#378
Merged
Conversation
ac0c213 to
2403e10
Compare
The packages that export ES modules do not have a `.js` extension on the
import paths, which means that the import path does not match an actual
file path (since the latter do have a `.js` extension). This means they
cannot be properly resolved by Node.js or the browser.
However, since we're using TypeScript to transpile, and we're using the
legacy "node" module resolution, the import paths are preserved and end
up not having a `.js` extension, while the transpiled files to have it.
There are two main ways to deal with this:
1. Use TS configuration `{"module":"esnext","moduleResolution":"bundler"}`
and use a bundler that produces import paths matching an actual file.
Note: using TypeScript in this case would leave the imports as-is
and require users to use a bundler, so it would not constitute an
ES module that just works with node/browser, which is the problem we
actually set out to solve.
2. Use TS configuration `{"module":"nodenext","moduleResolution":"nodenext"}`
and use `{"type":"module"}` in package.json. This will instruct tsc to
produce output that matches the package configuration, so ES module in
this case.
The advantage with (1) is that it requires no addition of a `.js`
extension to the imports in the .ts(x) source files. Unfortunately this
requires TS 5 (we currently use TS 4) _and_ the use of a bundler to
build (which we currently do not use). The advantage with (2) is that it
requires no changes to how we build, but it does required adding a `.js`
extension to all import paths in the source code.
Since addition of a bundler adds a layer of complexity in maintenance
for a repository that should be easily accessible, it seems option (2) is
preferable (and also can be done without having to do a major TS ugprade
first).
lekoaf
approved these changes
Feb 6, 2025
2403e10 to
ea0db27
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The packages that export ES modules do not have a
.jsextension on the import paths, which means that the import path does not match an actual file path (since the latter do have a.jsextension). This means they cannot be properly resolved by Node.js or the browser.However, since we're using TypeScript to transpile, and we're using the legacy "node" module resolution, the import paths are preserved and end up not having a
.jsextension, while the transpiled files to have it.There are two main ways to deal with this:
{"module":"esnext","moduleResolution":"bundler"}and use a bundler that produces import paths matching an actual file. Note: using TypeScript in this case would leave the imports as-is and require users to use a bundler, so it would not constitute an ES module that just works with node/browser, which is the problem we actually set out to solve.{"module":"nodenext","moduleResolution":"nodenext"}and use{"type":"module"}in package.json. This will instruct tsc to produce output that matches the package configuration, so ES module in this case.The advantage with (1) is that it requires no addition of a
.jsextension to the imports in the .ts(x) source files. Unfortunately this requires TS 5 (we currently use TS 4) and the use of a bundler to build (which we currently do not use). The advantage with (2) is that it requires no changes to how we build, but it does required adding a.jsextension to all import paths in the source code.Since addition of a bundler adds a layer of complexity in maintenance for a repository that should be easily accessible, it seems option (2) is preferable (and also can be done without having to do a major TS ugprade first).
Describe your changes
Please include a summary of the change, a relevant motivation and context.
Issue ticket number and link
Checklist before requesting a review