lukeed / tsm

TypeScript Module Loader
MIT License
1.18k stars 19 forks source link

Support native ESM packages #7

Closed maxmilton closed 2 years ago

maxmilton commented 2 years ago

When importing *.js files from packages which have "type": "module" an ERR_REQUIRE_ESM error is thrown:

> node -r tsm index.ts

/home/max/Projects/repro-tsm-native-esm/index.ts:1
import getPort from 'get-port';
                                                                                                                                                                                                                    ^

Error [ERR_REQUIRE_ESM]: require() of ES Module /home/max/Projects/repro-tsm-native-esm/node_modules/.pnpm/get-port@6.0.0/node_modules/get-port/index.js from /home/max/Projects/repro-tsm-native-esm/index.ts not supported.
Instead change the require of index.js in /home/max/Projects/repro-tsm-native-esm/index.ts to a dynamic import() which is available in all CommonJS modules.
    at Object.apply (/home/max/Projects/repro-tsm-native-esm/index.ts:1:213)
    at Object.<anonymous> (/home/max/Projects/repro-tsm-native-esm/index.ts:20:34)
    at Module.t._compile (/home/max/Projects/repro-tsm-native-esm/node_modules/.pnpm/tsm@2.1.0/node_modules/tsm/require.js:1:935)
    at Object.loader (/home/max/Projects/repro-tsm-native-esm/node_modules/.pnpm/tsm@2.1.0/node_modules/tsm/require.js:1:948) {
  code: 'ERR_REQUIRE_ESM'
}

I've created a minimal reproducible case at https://github.com/maxmilton/repro-tsm-native-esm.

This will become increasingly common as more packages migrate to native ESM only.

The same issue popped up on the https://github.com/egoist/esbuild-register project:

and had a fix: https://github.com/egoist/esbuild-register/commit/a540af754e67f74ba914d35f36ccb7b29c6c2a43.

Seems like a tricky thing to solve without a big hit from extra disk I/O, catching the error like esbuild-register does, or passing through all .js to the esbuild compiler. Catching the error seems like the lesser of the evils but perhaps you'll have a better idea.

lukeed commented 2 years ago

thanks, forgot about this. I have .mjs support when using --require but either need to look at every .js file's closest package.json (could be costly) or just always attach .js as a something to rewrite (might also be costly, but for different reasons). Or yeah, catching errors probably be the cheapest here. I'll measure this & see if there's a concrete answer here.