nodejs module search strategy

We all know that nodejs currently supports es6 modules and commonjs modules. In this world where everything can be a module, this article will explore what kind of strategy nodejs uses to find the corresponding module when we reference it. of the module

Module classification

Modules in nodejs are mainly divided into two categories. One is the module provided by nodejs, called core module, and the other It is a module written by users, called File module. Their relationship is shown in the figure below

file module

File modules are divided into custom modules and modules introduced in the form of paths depending on how they are referenced. Custom modules usually exist in the form of packages. For example, the packages we download from npm are custom modules. Modules introduced in the form of paths are usually encapsulated modules written by the user themselves. When introducing, the user needs to specify the real path of the module. The difference between the two is the introduction method. For example, the following code

var express = require('express');//自定义模块
var usersRouter = require('./routes/users');//以路径形式引入的模块

The similarity between the two is that because they belong to the same file module, they are dynamically loaded at runtime when they are introduced. At the same time, due to dynamic loading, path analysis, file positioning, dynamic compilation and other operations are required when introducing them.

core module

The core module can be understood as the built-in core function module of nodejs. It will be compiled into a binary file when the nodejs source code is compiled. When nodejs starts, these core modules will be directly loaded into the memory, so when the core module is loaded, relatively For file modules, the core module does not require file location and dynamic compilation when referencing it, and has certain advantages in speed. Common modules such as http, fs, path, etc. all belong to the core module.

Loading order

Let’s draw the conclusion first:Cache>Core module>File module

Nodejs has made a certain degree of optimization for module loading. All files will be cached as long as they are referenced once. The next time they are referenced, they will first check whether there are corresponding files in the cache and load them from the cache first. This has been reduced. Secondary expenses. But unlike the browser's cache, nodejs caches objects that have been analyzed and compiled. Whether it is a file module or a core module, the cache will be checked first before being referenced. However, the cache check of the core module is better than the cache check of the file module. priority.

path analysis

  • Core modules:

Since the core module is loaded into memory when nodejs is compiled, the core module does not need to perform path analysis and file location, and its loading speed is only as fast as caching.

  • Modules introduced in path form:

 Since the exact path is specified, the require method will convert the specified path into a real path on the hard disk when introduced, and use this path as an index to cache the compiled results. Since the path is specified, this form of file module can save a lot of time during path analysis. It is faster than a custom module but slower than the core module.

  • Custom modules:

Loading custom modules is more complicated than modules introduced in the form of paths. The main reason is that path analysis and file location take more time. The search for custom components follows the following rules:

  1. Search the node_modules directory in the current directory to see if there is a match. If so, hit the file
  2. Look for node_modules under the parent directory, if any, hit the file
  3. Follow this rule and search in the parent directory until you reach node_modules in the root directory.

Since it must be searched layer by layer, the path analysis of custom modules requires a large number of events, which will lead to low search efficiency. Therefore, the loading performance of custom modules is slower than that of loading in path form.

File location

After completing the path analysis, node will analyze the file extension. Currently, the commonjs specification and es6 modules allow file identifiers without extensions. If the identifier does not have an extension, it will be processed according to .js, . Try node, .json in this order one by one.

Of course, there is also a situation where the current path hits not a file but a directory, then:

  1. First, the package.json file will be found in the hit directory and parsed with JSON.parse, and the value of the main attribute in the json file will be taken out as the hit file.
  2. If package.json or the corresponding main attribute cannot be found, the index file under this directory will be used as the hit file. It will still be tried one by one in the order of .js, .node, and .json.
  3. If the index is still not found, then the file positioning fails this time, and the path traversal rules mentioned above will be followed and the search will continue to the next level.

Give a chestnut

For path analysis and file positioning, we can look at the following examples to deepen our understanding.

The picture below is the directory structure of the entire project

The above contains three modules, namely nameByJson, parent, and root. The corresponding codes are as follows:

nameByJson

//目录:moduleLocation/child/child2/node_modules/nameByJson/real.js
module.exports = function nameByJson() {
    console.log('nameByJson');
};
//目录:moduleLocation/child/child2/node_modules/nameByJson/package.json
{
  "main": "real.js"
}

parent

//目录:moduleLocation/child/node_modules/parent/index.js
module.exports = function parent() {
    console.log('parent');
};

root

//目录:moduleLocation/node_modules/root.js
module.exports = function root() {
    console.log('root');
}

Entry file

//目录:moduleLocation/child/child2/index.js
var nameByJson = require('nameByJson');
var parent=require('parent');
var root =require('root');
nameByJson();//输出nameByJson
parent();//输出parent
root();//输出root

We run the entry file index.js and we can find that the output is consistent with our expectations.Here is the source file of the sample code, if you are interested You can download it and take a look

Guess you like

Origin blog.csdn.net/xiaomingelv/article/details/96461786