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:"."
tobaseUrl:"./"
– 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
3 Answers
Reset to default 5After 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/*"]
}
}
}