Since the end of 2023 Node V20 will become in Active LTS. After that you may feel tempted to upgrade for the new major release of runtime. And there’re chances you will encounter such error
Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '...' is not supported resolving ES modules imported from ...
TL;DR
Use this custom loader
UPD: you may also want slightly to modify the provided loader to not use deprecated --loader
flag but --import
flag instead. More information about it here
Table of contents
Open Table of contents
Why Did It Happen In The First Place?
Take a look at this pull request. --experimental-specifier-resolution
and --es-module-specifier-resolution
simply just got deprecated.
The reason behind it – users can replicate the behavior of these flags on their own.
But let’s first figure out more details on occurring error.
What Does This Error Even Mean?
Pay attention to such imports/exports:
export * from "./http";
We’re trying to reexport everything from index.js
implicitly. index.js
isn’t mentioned here anywhere, that’s what brings trouble. We could simply fix it by adding /index.js
at then:
export * from "./http/index.js";
But it wouldn’t help us if the problem code were in library. Then meet the loaders!
ECMAScript Modules Loaders
According to the loader’s Node.js team the loaders are needed to implement use cases that were not initially in ES Modules. Looks like they’re talking about our case!
How to accomplish the desired behavior:
- Head out to this repo
- Copy
loader.js
file to root of your newly upgraded project - Add additional dependency to you project (
"resolve": "^1.22.1"
) - Make sure that dependency is NOT in your
devDependencies
- Install updated dependencies
- Add flag to node like that:
node --loader=./loader.js
- Don’t forget to include this flag to all places where
node
is calling your application (even in Dockerfile)
But why would we copy the source code and haven’t installed an appropriate library? First of all, the linked repo doesn’t come with any npm package. Some guy have uploaded it to npm anyways, but I don’t want to to bring some random dependency into my code. You might have a different opinion though 🤷♂️
Bonus: Working With Such Libraries From TypeScript
If you would like to work with library that is using such loader or previously used deprecated flag you’d need to make some tweaks to your configs
Let’s start with tsconfig.json
(most unrelated settings are omitted):
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "Node10"
}
}
The biggest key to make it work is to set moduleResolution
to Node10
. This way TypeScript will properly parse typings that are being supplied with library.
The second thing to do is you set type
to module
inside package.json
and you good to go.
Thanks for reading!