简体   繁体   中英

ESM importing all files from folder with index.js not working

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.

Import index.js automatically in esm is an experimental feature in the current version in node.js. You can use flag --experimental-specifier-resolution=node while staring server.

EX- node --experimental-specifier-resolution=node index

Plz refer this link for more info https://nodejs.org/api/esm.html#esm_resolver_algorithm

In order to make this work with "type":"module", you need to import including filename and extension ie "index.js", it won't look for index.js by default, other files also need to include the extension ieajs

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';

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM