admin管理员组

文章数量:1356869

I got a node web app project that uses regular JS.

I am trying to set some paths using a jsconfig.json. I tried using node default's Subpath imports and even thou it does work, the vscode intellisense stopped working.

I found out you could use jsconfig.json so I set this file

{
  "pilerOptions": {
    "target": "es6",
    "module": "monjs",
    "baseUrl": "./",
    "paths": {
      "@controllers/*": ["node/controllers/*"],
    },
  },
  "exclude": ["node_modules"]
}

And on my package.json I added

"type": "module",

My folder structure is

├── node
│    └──controllers
│         └── foo.js
├── server.js
├── jsconfig.json
└── package.json

But when I try to import from server.js

import { foo } from '@controllers/foo.js'
// or import { foo } from '@controllers/foo'

foo.js

export const foo = 'Hello server'

I get

node:internal/process/esm_loader:74
     internalBinding('errors').triggerUncaughtException(

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@controllers/foo.js' imported from /Users/Alvaro/Sites/test/server.js

 at new NodeError (node:internal/errors:363:5)
 at packageResolve (node:internal/modules/esm/resolve:698:9)
 at moduleResolve (node:internal/modules/esm/resolve:739:18)
 at Loader.defaultResolve [as _resolve] (node:internal/modules/esm/resolve:853:11)
 at Loader.resolve (node:internal/modules/esm/loader:89:40)
 at Loader.getModuleJob (node:internal/modules/esm/loader:242:28)
 at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:73:40)
at link (node:internal/modules/esm/module_job:72:36) {
code: 'ERR_MODULE_NOT_FOUND'

I got a node web app project that uses regular JS.

I am trying to set some paths using a jsconfig.json. I tried using node default's Subpath imports and even thou it does work, the vscode intellisense stopped working.

I found out you could use jsconfig.json so I set this file

{
  "pilerOptions": {
    "target": "es6",
    "module": "monjs",
    "baseUrl": "./",
    "paths": {
      "@controllers/*": ["node/controllers/*"],
    },
  },
  "exclude": ["node_modules"]
}

And on my package.json I added

"type": "module",

My folder structure is

├── node
│    └──controllers
│         └── foo.js
├── server.js
├── jsconfig.json
└── package.json

But when I try to import from server.js

import { foo } from '@controllers/foo.js'
// or import { foo } from '@controllers/foo'

foo.js

export const foo = 'Hello server'

I get

node:internal/process/esm_loader:74
     internalBinding('errors').triggerUncaughtException(

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@controllers/foo.js' imported from /Users/Alvaro/Sites/test/server.js

 at new NodeError (node:internal/errors:363:5)
 at packageResolve (node:internal/modules/esm/resolve:698:9)
 at moduleResolve (node:internal/modules/esm/resolve:739:18)
 at Loader.defaultResolve [as _resolve] (node:internal/modules/esm/resolve:853:11)
 at Loader.resolve (node:internal/modules/esm/loader:89:40)
 at Loader.getModuleJob (node:internal/modules/esm/loader:242:28)
 at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:73:40)
at link (node:internal/modules/esm/module_job:72:36) {
code: 'ERR_MODULE_NOT_FOUND'
Share Improve this question edited Sep 29, 2021 at 14:54 Álvaro asked Sep 29, 2021 at 12:04 ÁlvaroÁlvaro 2,6084 gold badges30 silver badges67 bronze badges 12
  • change baseUrl:"." to baseUrl:"./" – Sachin Ananthakumar Commented Sep 29, 2021 at 12:25
  • @SachinAnanthakumar, It does not fix it. – Álvaro Commented Sep 29, 2021 at 12:28
  • did you add a export default in foo.js ? – Sachin Ananthakumar Commented Sep 29, 2021 at 12:39
  • Yes of course, export default.... – Álvaro Commented Sep 29, 2021 at 12:41
  • I am not sure why it doesn't work, is that the plete error stack trace? – Sachin Ananthakumar Commented Sep 29, 2021 at 12:42
 |  Show 7 more ments

3 Answers 3

Reset to default 5

After hours of research, I have found that it is very difficult to have a custom alias path while using esm and very easily configured for monjs,

but it can be achieved, in a slightly different manner when you use esm, I will write the solution for esm implementation in method 1 and then for monjs in method 2

Method 1

Step 0:

remove jsconfig.json

Step 1:

in your package.json add an exports property,

"name": "package-name"

"exports":{
   "./@controllers/" : "./node/controllers/"
}

Note: Don't forget the '/' after the @controllers and /node/controllers/

Step 2

you will have to import the file

  import {foo} from "package-name/controllers/index.js" 
/*
package-name is the same value as the 'name' property in
the package.json
*/

to learn more about exports property in package.json refer here

------------------------------XXXXXXXX----------------------------------

Method 2

you can't use es modules in this method

Step 0

install module-alias package.

npm i module-alias

remove type:module if it exists in package.json or change the value to monjs;

Step 1

Add the below code at the starting line of the file which is specified as the entry point in package.json

require(module-alias/register)

check the main property in package.json in the author's case it should be server.js.

in package.json add this

"_moduleAliases": {
  "@root" : ".", // Don't forget to mnetion this
  "@controllers" : "node/controllers/*"
}

Now you can require modules from directries like below

const {foo} = require("@controllers/foo.js") // if foo is named export 

//or

const foo = require("@controllers/foo.js");

you can refer more about module-alias library here

What you have tried is almost correct.

you can get aliases working but it has to start with #.

for example: in package.json

"imports": {
    "#app": "./app.js"
}

and in jsconfig.json

{
  "pilerOptions": {
    "paths": {
      "#app": ["./app.js"]
    }
  }
}

Using module-alias you can import your jsconfig.json file, iterate over its content, and create the alias programmatically.

In your entry file:

    const path = require("path");

    const moduleAlias = require("module-alias");
    const jsConfig = Object.entries(require("./jsconfig.json").pilerOptions.paths);

    for (let i = 0; i < jsConfig.length; i++) {
        const [key, val] = jsConfig[i];

        const k = key.replace("/*", "");
        const p = path.join(__dirname, val[0]).replace("/*", "");

        moduleAlias.addAlias(k, p);
    }

The value is val[0] because jsconfig defines each path as an array. Official example from the visualstudio website.

{
  "pilerOptions": {
    "baseUrl": ".",
    "paths": {
      "ClientApp/*": ["./ClientApp/*"]
    }
  }
}

本文标签: javascriptES modules and jsconfigjson Error ERRMODULENOTFOUNDStack Overflow