Nodejs's non-core modules (Core module) load is mainly used by module.js.
The Project main module (index.js/main.js, etc.) should be loaded using Runmain () in Module.js, and the other JS module loading process is basically:
1, Get JS file information;
2,new Module ();
3, read the contents of the JS file, encapsulated into a function, while injecting the module itself, Module.exports, packaged require functions and other variables;
4, executing the encapsulated function in a context;
5, return to Module.exports;
The main code is as follows
module.js: // Loads A module at the given file path. Returns that module ' s
//' exports ' property.Module.prototype.require =function(path) {assert (path,' Missing path '); ASSERT (util.isstring (path),' Path must be a string '); returnModule._load (Path, This);};//Check the cache for the requested file.//1. If A module already exists in the Cache:return its exports object.//2. If the module is Native:call ' Nativemodule.require () ' with the//filename and return the result.//3. Otherwise, create a new module for the file and save it to the cache.//Then there is it load the file contents before returning its exports//object.Module._load (filename, This) {If (FileNameinchModule._cache) Return Module._cache[filename];
varmodule =NewModule (filename, parent); Module._cache[filename]=module; Module.load (filename);
The problem of cyclic dependencies can be solved by putting the module into the cache and then loading the content. See the cycles section of https://nodejs.org/api/modules.html.
returnModule.exports;} Module.prototype.load (filename) {varExtension = path.extname (filename) | |'. js ';
Module._extensions[extension] ( This, filename) { varContent = Fs.readfilesync (filename, ' utf-8'); Module._compile (content, filename); }}//Run The file contents in the correct scope or sandbox. Expose//the correct helper variables (require, module, exports) to//The file.//Returns exception, if any.Module.prototype._compile =function(content, filename) {functionrequire (path) {returnself.require (path); } Require.main=Process.mainmodule; //Enable support to add extra extension typesRequire.extensions =module._extensions; Require.cache=Module._cache; //TODO: What's the difference in how each module is loaded into its own context? //Set The environ variable node_module_contexts=1 to make NODE load allmodules in their own context.//module._contextload = (+process.env[' node_module_contexts ') > 0);//if (module._contextload) {...} //Create wrapper function varwrapper =nativemodule.wrap (content); //wrapper = ' (function (exports, require, module, __filename, __dirname) {' + content + ' \ n}); ' //Runinthiscontext () can be thought of as an eval () performed in a context environment. //compiledwrapper equivalent to eval (' (function () {...}) ') The result, that is, the real function. varCompiledwrapper =Runinthiscontext (wrapper, {filename:filename}); //the difference between module.exports and exports://This only passes the exports reference, and above Module._load () returns the Module.exports, so after assigning the module.exports to the value,//exports still points to the previous module.exports. varargs =[Self.exports, Require, self, filename, dirname]; //The function that actually executes compiledwrapper, that is, executes the content of Filename.js. returncompiledwrapper.apply (self.exports, args);}
Runinthiscontext () is Runinthiscontext () in Vm.js, Vm.runinthiscontext () calls src/node_contextify.cc in RunInThisContext ()。
Https://github.com/joyent/node/blob/master/lib/vm.js
https://github.com/joyent/node/blob/master/src/node_contextify.cc
Nodejs JS Module loading