Consider this very simple project: esm-test
Runs on Node.js v13.
This project has "type":"module"
in his package.json
so Node.js will treat by default all files .js
as ECMAScript modules. See: ECMAScript Modules - Enabling.
It has the following very simple structure:
- package.json
- src/
- stuff/
- a.js
- b.js
- index.js
- app.js
The file app.js
is the package entry point.
My purpose is to import all files from stuff/
folder using the index.js
file. I know that in ES6, having an index.js
file in a folder lets you perform an import from the folder implicitly without specifying the index.js
in the import statement.
So I can do:
import { a, b } from './stuff'
Instead of:
import a from './stuff/a.js'
import b from './stuff/b.js'
But it's not working for me. It shows the following error:
internal/modules/esm/default_resolve.js:96
let url = moduleWrapResolve(specifier, parentURL);
^
Error: Cannot find module C:\projects\esm-test\src\stuff imported from C:\projects\esm-test\src\app.js
at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:96:13)
at Loader.resolve (internal/modules/esm/loader.js:72:33)
at Loader.getModuleJob (internal/modules/esm/loader.js:156:40)
at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:42:40)
at link (internal/modules/esm/module_job.js:41:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
With CommonJS modules works. But I want to do it with ESM.
Can you help me with this please.
Consider this very simple project: esm-test
Runs on Node.js v13.
This project has "type":"module"
in his package.json
so Node.js will treat by default all files .js
as ECMAScript modules. See: ECMAScript Modules - Enabling.
It has the following very simple structure:
- package.json
- src/
- stuff/
- a.js
- b.js
- index.js
- app.js
The file app.js
is the package entry point.
My purpose is to import all files from stuff/
folder using the index.js
file. I know that in ES6, having an index.js
file in a folder lets you perform an import from the folder implicitly without specifying the index.js
in the import statement.
So I can do:
import { a, b } from './stuff'
Instead of:
import a from './stuff/a.js'
import b from './stuff/b.js'
But it's not working for me. It shows the following error:
internal/modules/esm/default_resolve.js:96
let url = moduleWrapResolve(specifier, parentURL);
^
Error: Cannot find module C:\projects\esm-test\src\stuff imported from C:\projects\esm-test\src\app.js
at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:96:13)
at Loader.resolve (internal/modules/esm/loader.js:72:33)
at Loader.getModuleJob (internal/modules/esm/loader.js:156:40)
at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:42:40)
at link (internal/modules/esm/module_job.js:41:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
With CommonJS modules works. But I want to do it with ESM.
Can you help me with this please.
Share Improve this question edited Apr 10, 2021 at 13:00 Yves M. 31k24 gold badges109 silver badges149 bronze badges asked Jan 1, 2020 at 21:08 David FerreiraDavid Ferreira 1,7861 gold badge23 silver badges30 bronze badges 1- Do you see @Vivek's answer? If it solves your problem, accept his answer. I see his answer. It's a perfect answer. – Mir-Ismaili Commented Nov 14, 2020 at 0:37
3 Answers
Reset to default 8Import index.js
automatically in ESM is an experimental feature in the current version in ode.js. You can use flag --experimental-specifier-resolution=node
while starting server.
E.g. node --experimental-specifier-resolution=node index
Please refer this link for more info.
In order to make this work with "type":"module", you need to import including filename and extension i.e. "index.js", it won't look for index.js by default, other files also need to include the extension i.e. a.js
a.js / b.js
class a {
constructor(name) {
this.name = name;
}
sayName() {
console.log('Hi, my name is ', this.name + '.');
}
}
export default a;
./stuff/index.js
import a from './a.js';
import b from './b.js';
export {
a,
b
};
//Or "export default" depending on your needs.
export default {
a,
b
};
app.js
import { a, b } from './stuff/index.js'
If you have multiple named exports, you need to import like this.
import * as a from './a.js';
In the current version of Node (20 as of this writing), the file extension is always required for relative imports, and the full relative path must be specified: import { a, b } from './stuff/index.js'
(reference)
However, this behavior can be customized. Here's a custom loader that restores the CJS behavior of not requiring extensions and automatically resolving 'index' imports: https://github./nodejs/loaders-test/tree/main/monjs-extension-resolution-loader