# Node Module Resolution
# Core modules
First, Node.js checks if your import is a core Node.js module, anything like, os
, node:asserts
, fs
, etc.
import { join } from 'node:path'
import { writeFile } from 'fs'
# Relative modules
- Secondly, Node.js checks if our imports start with
/
,./
, or../
. If it does, Node.js checks this path for files and directories and treats the import as a path. - If the path starts,
/
Node.js will look for the module from the root of our file system. - If the path begins with
./
of../
Node.js will search for the module relative to the current file's location.
Let's say we are trying to import this module:
import { bar } from './foo'
Node.js will run the following checks import note that if one of these checks passes, the Node.js will not continue to the next steps
- if
foo
exists, execute by file extension. In this case, Node.js will throw anERR_UNKNOWN_FILE_EXTENSION
because foo doesn't have any file extension. - if
foo.js
exists, executes as a javascript module - if
foo.json
exists, parses json, and returns JS object - if
foo.node
exists, runs as a binary add-on (opens new window). - if
foo/package.json
Node.JS will search for the main field. If present, Node.js will run steps 1–4 and 6–8 for the given path inmain
- if
foo/index.js
exists, executes as a javascript module - if
foo/index.json
exists, parse json, and rerun object - if
foo/index.node
exists, runs as a binary add-on.
If everything fails, Nodejs will throw ERR_MODULE_NOT_FOUND
# Alias Modules
Thirdly Node.js checks if our imports start with #
. This import is like an alias to other files in our project, like the Webpack alias (opens new window) or TypeScript path (opens new window).
In general, you can define an alias that starts with # to a given path in your project
{
"name": "my-site",
"imports": {
"#foo": "bar.js"
}
}
When Node.js resolve an import like this, it starts to go through all the parent folders of the current file and process the first package.json it finds
Given this directory tree
├── worspace/
└── package.json
├── app-1/
| ├── package.json
| └── index.js
└── app-2/
└── index.js
- If we will run node
workspace/app-1/index.js
Node.js will process only thepackage.json
inworkspace/app-1/pacakge.json
. - But if we will run node
workspace/app-2/index.js
Node.js will check thepackage.json
workspace/package.json
Let's say we are trying to import this module:
import { bar } from '#foo'
Node.js will run the following checks import note. If one of these checks fails Node.js, it will not continue to the next steps
- Scans for the closes
package.json
- Search for the
imports
field - Return resolved path that is configured. Throw an error that fails to resolve.
# Self Import Modules
Fourthly, Node.js checks if the imports start with the name of our current scope.
Given this package.json
{
"name": "my-site",
"exports": {
"foo": "bar.js"
}
}
If we try to import my-site/foo
. We will run bar.js
.
import { bar } from 'my-site/foo'
The way that Node.js resolve this config is very similar to the resolution algorithm of the imports field. We can still import foo
form anywhere in the project, but instead of starting with #
the import must start this with our package name.
# Node Modules
And Finally, if none of our previous checks passed, Node.js will try to resolve the import from the node_modules
directory.
Given this workspace,
├── worspace/
└── node/
└── worspace/
└── source.js
Node.js will check the flowing paths to see if they contain node_moduels
directory before throwing an error
// checks order
1. /home/node/worspace/node_modules
2. /home/node/node_modules
3. /home/node_modules
4. /node_modules
In general, Node.js will check every parent folder in the tree until they get to the root, meaning every package installed on the roots node_modules
will be available to all the Node.js programs in your machine.
Let's say we import this module.
import { bar } from 'foo'
Node.js will run the following checks for each parent directory in the tree until the root. import note that if one of these checks passes, the Node.js will not continue to the next steps
- if
node_modules/foo/package.json
exists and has an exports field, resolve the exports field, like in the Self Import Modules section but with foo module instead of our workspace - if
node_modules/foo
exists run the same file/directory resolving algorithm as in the relative modules section
If everything fails, and Nodejs fails and can't find any modules, it will throw ERR_MODULE_NOT_FOUND
.
Given this workspace
/
├── worspace/
| └── foo/
| └── index.js
├── home/
└── node/
└── worspace/
└── node_modules
└── source.js <-- IMPORT "foo"
Node.js will check all of these paths when trying to find our module.
/home/node/workspace/node_modules/
/home/node/node_modules/
/home/node_modules/
/node_modules/
/node_modules/foo/
/node_modules/foo/index.js
← n Lấy tham số từ CLI →