This is the 10th day of my participation in Gwen Challenge
One of the most frequently used methods in NodeJS is the require method. NodeJs follows the CommonJS specification, the core of which is to load other dependent modules via require.
A few questions
- Module. exports or exports is a global variable?
- Are modules loaded synchronously or asynchronously?
- Will circular references cause performance problems or errors?
What is a CommonJS
Each file is a module, with its own independent scope, variables, methods, etc., invisible to other modules. The CommonJS specification states that within each module, the module variable represents the current module. This variable is an object whose exports property (module.exports) is the interface to the outside world.
Node module classification
- Build-in modules — modules provided in C++ in Nodejs.
- Constant module — The module in Nodejs that defines constants.
- Native Module — modules provided in javascript form in Nodejs.
- Third Party Module – modules provided by third parties.
The module object
NodeJs provides a Module builder function inside. All modules are instances of Module.
Inside each module, there is a Module object that represents the current module. It has the following properties.
-
Properties of the Module object
module.id
The module’s identifier, usually the module’s file name with an absolute path.module.filename
The file name of the module, with an absolute path.module.loaded
Returns a Boolean value indicating whether the module has finished loading.module.parent
Returns an object representing the module that called the module (null for module.parent in the program entry file)module.children
Returns an array representing other modules used by this module.module.exports
Represents the output value of the module.
-
The module.exports property refers to the interface that the module exports. Other files that load the module actually read the module.exports variable. The module.exports property represents the interface that the current module exports. Other files that load the module actually read the module.exports variable.
-
Exports variable
We sometimes write things like:
// test.js
function test(){
console.log(test);
}
exports.test = test;
// result.js
const test = require("./test")
Copy the code
This also gets the correct result because the: exports variable points to module.exports. This equates to a line of command in the header of each module.
var exports = module.exports;
Copy the code
Note: you cannot assign a value to the exports variable directly, which would change the direction of exports from module.exports. Exports cannot be returned if the require method is used on any other module because the require method gets the module.exports value of any other module.
Suggestion: Export results using module.exports whenever possible.
Module flow
- Create a module
- Export module
- Load module
- Use the module
Method the require
Require is node’s method for loading and executing modules that export other files.
In NodeJs, each Module we introduce corresponds to a Module instance, including the entry file.
Complete steps:
-
Call the parent module’s require method (the parent module is the current module that calls the module)
require = function require(path) { return mod.require(path); }; Copy the code
-
Call Module’s _load method
-
Run the module. _resolveFilename command to obtain the Module path fileName
const filename = Module._resolveFilename(request, parent, isMain); Copy the code
-
Check whether a cache for the module exists according to fileName
- Call if a cache exists
updateChildren
Method updates the cache contents and returns the cache - If no cache exists, the execution continues
- Call if a cache exists
-
As a native module, the loadNativeModule method is called to load it
- If the load succeeds, the native module is returned
- Otherwise, continue
-
Generates a Module instance based on the current Module name (path) and the parent Module object:
const module = cachedModule || new Module(filename, parent); Copy the code
-
Then determine whether the module is an entry file
if (isMain) { process.mainModule = module; module.id = '. '; } Copy the code
-
Store an instance of the Module in the Module cache
Module._cache[filename] = module; Copy the code
-
The instance of the module calls its own load method to load the module according to fileName
module.load(filename); Copy the code
-
Gets the suffix name of the module file
const extension = findLongestRegisteredExtension(filename); Copy the code
If the suffix name is in ES Module format (.mjs), determine whether the Module supports.mjs file parsing, and throw an exception if it does not.
-
Resolve module file contents by suffix name
Module._extensions[extension](this, filename); Copy the code
-
Read the file content according to fileName
content = fs.readFileSync(filename, 'utf8'); Copy the code
-
Compile and execute the read file, calling module’s _complile method:
module._compile(content, filename); Copy the code
_compile main content steps:
const compiledWrapper = wrapSafe(filename, content, this); const dirname = path.dirname(filename); const require = makeRequireFunction(this, redirects); let result; const exports = this.exports; const thisValue = exports; const module = this; result = compiledWrapper.call(thisValue, exports.require.module, filename, dirname); return result; Copy the code
The return value of the wrapSafe method
The code to obtain the above result is:
const wrapper = Module.wrap(content); return vm.runInThisContext(wrapper, { filename, lineOffset: 0.displayErrors: true.importModuleDynamically: async (specifier) => { const loader = asyncESM.ESMLoader; returnloader.import(specifier, normalizeReferrerURL(filename)); }});Copy the code
-
Change the loading status of this module to true
this.loaded = true; Copy the code
-
Loading succeeded.
conclusion
Through the above debugging process, the following conclusions can be drawn:
- In NodeJs, everything is Module from the entry file.
- Modules are loaded synchronously.
- Because of the caching mechanism, cyclic references to modules have little impact on performance, and cyclic references to modules can be incomplete and can cause errors
- The require module lookup process is as follows:
- The flowchart for resolving file paths is as follows:
In this paper, the
Learn interesting knowledge, meet interesting friends, shape interesting soul!
Everybody is good! I am the author of programming Samadhi, yi Wang, my public account is “programming Samadhi”, welcome to pay attention to, I hope you can give me more advice!
Knowledge and skills should be paid equal attention to, internal force and external power should be repaired simultaneously, theory and practice should grasp both hands, both hands should be hard!