'How require work under the hood in NodeJS?
I try to understand how bootstrapping of nodeJS works, but I am stacked with the function require
- First use of require inside
internal/bootstrap/node.js
(See picture below) - require passed to this file in
src/node.cc
asnative_module_require
- node.cc take require from
internal/bootstrap/loaders.js
(which executed before step 1) internal/bootstrap/loaders.js
useinternalBinding
, which usegetInternalBinding
getInternalBinding
create from ...src/node_binding.cc
, looks a little bit complicated, but my case ("native_module"
from step 4) isfindModule(modlist_internal...
modlist_internal
saved innode_module_register
- which is called from
napi_module_register
- which is called from
NAPI_MODULE
- but I cannot find where
NAPI_MODULE
is used (except for test and bench)
I use 16.14.0 LTS version of nodeJS from GitHub
What I am trying to do? Nothing special, just curiosity, I also study the source code of the old project, which can run node inside the browser https://github.com/olydis/node-in-browser, but it use old version of nodeJS (with different require
), and the project is not updated few years. Also, I am wondering, how stackblitz.com launch a modern version of nodeJS inside the browser.
P.S. there is also folder lib\internal\modules\ which is somehow related to require
and import
but I don't think its used in bootstrapping process, maybe a little bit later
P.P.S. I know only javaScript, so I can miss something important in C++ source code
Solution 1:[1]
In the .data section of the node executable there are C++ strings that contain native js sources. In the .text section of the node executable are executable code fragments compiled from those strings. V8 maintains the bindings between the native js sources and the executable code fragments through mappings inside the global object of the V8 instance's isolate, and node sets up the V8 isolate with the correct mappings/bindings during initialization. Require is one of the native js sources.
Further js code is converted into executable code and data by node through V8. Your program, which calls require, is such js code. Since require is a native js module, a binding to executable code exists, so V8 knows which address to use when compiling the call. The implementation of require has logic to find out whether its argument is a native module or not, as there's different logic for importing native vs non-native modules.
So a call to require works by getting compiled to a call to a pre-compiled function that is part of the node executable that V8 knows about thanks to node's set up of V8.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |