ES Modules and `"moduleResolution":"NodeNext"` in v9
Context:
- https://github.com/developit/microbundle/issues/1019#issuecomment-1384721680
- https://github.com/donmccurdy/glTF-Transform/issues/824
In glTF Transform I ran into some conflicts between how TypeScript bundles types, and upcoming changes to Node.js module resolution. I think Luma and Deck will hit the same problems in v9 (tested against the alpha release), for any TS project using a tsconfig.json like these:
{
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"target": "esnext",
}
}
{
"compilerOptions": {
"module": "node16",
"moduleResolution": "node16",
"target": "node16",
}
}
The only fix I'm aware of is to make sure our generated *.d.ts files do all file imports with .js extensions. Perhaps it's possible to configure the build tools to do that, but personally I've found it easier to just add "moduleResolution": "nodenext", in my own tsconfig.json, which enforces .js extensions on all imports in source files.
Also -- the fix above should be fully backwards-compatible, so there's no problem with making that change in v9.1 instead of v9.0 if we prefer.
In loaders.gl we run a script call add-js-to-imports
#/bin/sh
echo '# Adding .js to import statements in dist folders'
find modules/*/dist -name "*.js" -exec sed -i '' "s/from '\.\(.*\)';/from '.\1.js';/" {} \;
find modules/*/dist -name "*.js" -exec sed -i '' "s/from '\.\(.*\)\.js\.js';/from '.\1';/" {} \;
That looks like a good solution to me, and definitely less churn than changing all source imports. Potentially then, we'd put something like that in each repository? It doesn't seem like that script is running in loaders.gl now, I don't see it called anywhere, and the suffixes are missing from published types –
https://unpkg.com/@loaders.gl/[email protected]/dist/index.d.ts
It seems this affects node16 module resolution in typescript, and not just nodenext. This section of the TS docs was helpful for me:
https://www.typescriptlang.org/docs/handbook/modules/reference.html#node16-nodenext-1
@Pessimistress
There is a need of adding explicit .js extensions to import statements in generated code as required by Node ESM?
Does the new ocular setup have a plugin to do this (I was assuming one of the plugins you used in the last PR did this), or do we need to add back post processing scripts?
https://github.com/visgl/deck.gl/blob/x/esm/tsconfig.module.json
@donmccurdy Can this be closed with the latest ocular changes?
Yes, the change to ocular, post-processing type definitions to include .js extensions like this ...
// modules/foo/dist/index.d.ts
export type { Foo } from "./foo.js";
... does resolve this issue. 👍🏻