Nodejs module loading and running principle, nodejs module Loading
Preface
When Nodejs is used, it is inevitable to reference third-party modules. Some of them are provided by Nodejs (for example, http, net ...), some are published on npm (for example, mssql, elasticsearch ...)
This chapter focuses on three issues:
- Node. js module loading process.
- The application startup process.
- How does an application load dependency modules.
1. Module Loading Process
Nodejs modules can be divided into four types:
A) builtin module Nodejs provides modules in the form of C ++.
B) constant module Nodejs defines the constant module.
C) native module Nodejs provides modules in the form of javascript.
D) third-party modules provided by third parties.
Let's first look at the process of generating builtin module and native module.
Native JS module generation is relatively complex. After compilation, A node_natives.h is generated in the/out/release/obj/gen directory.
This file is generated by js2c. py. It converts all js files under the lib directory in the node. js source code into ASCII code and stores them in the corresponding array.
Builtin C ++ module generation process is relatively simple. Every module entry of builtin C ++ is extended into a func using the macro NODE_MODULE_CONTEXT_AWARE_BUILTIN. For example, for the tcp_wrap module, it is extended to the static void register_tcp_wrap () attribute (constructor) function.
Anyone familiar with GCC knows that the function modified by attribute (constructor) will be executed before the main () function of Nodejs. That is to say, builtin C ++ module will be in main () the function is previously loaded into the modlist_builtin list, while modlist_builtin is a pointer of the struct node_module type. get_builtin_module () traverses and searches for the required modules.
In fact, both the naive JS module and builtin C ++ module will eventually be compiled into executable files. The extraction methods are very different. js module uses process. binding ('natives '), while C ++ module uses get_builtin_module () directly ().
A binding () function is provided in node. cc. When require () is used to reference another module, the binding () function is introduced. Next we will analyze this function:
As you can see, the function mainly serves three modules: builtin, constants, and native.
Builtin has the highest priority and will be searched in modlist_builtin. The process is very simple. Just traverse the entire list and find the module with the same name. Once found, the module's registration function is executed first, and then the data exports is returned.
The constants module has a second priority, and the constant definition in Nodejs is exported through constants.
Native has the lowest priority.
2. Application Startup Process
As a flowchart, it describes test. js as the parameter to start and finally be executed. The entire process can be divided into four steps:
1. Executable File node: the node entry, which plays an important role in environment preparation during startup
2. src/node. js: Startup Script
3. Native Module: Prepare for execution of module. js
4. module. js: native module, used to load, compile, and execute applications
How to load dependency modules for an application
As mentioned above, NativeModule. require () is only responsible for referencing natives module, which is sufficient for lib/module. js.
However, it is obvious that the application not only needs to reference the matives module, but also the third-party module. Let's take a look at the Module. prototype. _ require () function in module. js.