Detailed explanation of the require () method

Time:2021-12-4

One method in nodejs that we use most frequently is the require method. Nodejs follows the commonjs specification, the core of which is to load other dependent modules through require.

Several questions

  1. Are module.exports or exports global variables?
  2. Is the module loaded synchronously or asynchronously?
  3. Will circular references cause performance problems or errors?

What is commonjs

Each file is a module with its own independent scope, variables, and methods, which are not visible to other modules. The commonjs specification specifies that within each module, the module variable represents the current module. This variable is an object whose exports attribute (i.emodule.exports)It is an external interface.

Classification of node modules

  1. build-in modules——Modules provided in C + + form in nodejs.
  2. constant module——The module that defines constants in nodejs.
  3. native module——Modules provided in the form of JavaScript in nodejs.
  4. Third party module——Modules provided by third parties.

Module object

Nodejs internally provides a module build function. All modules are instances of module.

Inside each module, there is a module object representing the current module. It has the following properties.

  • Properties of the module object

    • module.idThe identifier of the module, usually the module file name with an absolute path.
    • module.filenameThe file name of the module with an absolute path.
    • module.loadedReturns a Boolean value indicating whether the module has completed loading.
    • module.parentReturns an object representing the module calling the module (the module.parent of the program entry file is null)
    • module.childrenReturns an array representing other modules to be used by the module.
    • module.exportsIndicates the value output by the module.
  • Module.exports property
    module.exportsProperty indicates the external output interface of the current module. Loading the module from other files is actually readingmodule.exportsVariable.module.exportsProperty indicates the external output interface of the current module. Loading the module from other files is actually readingmodule.exportsVariable.
  • Exports variable

We sometimes write:

// test.js
function test(){
    console.log(test);
}
export.test = test;

// result.js
const test = require("./test")

In this way, you can also get the correct results because the exports variable points to module. Exports. This is the same as the header of each module. There is one such command.

var exports = module.exports;

Note: you cannot directly assign a value to the exports variable, which will change the direction of exports and no longer point to module.exports. Using the require method in other modules cannot get the value assigned to exports, becauseThe require method obtains the value of module.exports of other modules

Suggestion: use as much as possiblemodule.exportsTo export the results.

Module flow

  • Create module
  • Export module
  • Load module
  • Use module

Require method

Require is the method node uses to load and execute modules exported from other files.

In nodejs, any module we introduce corresponds to a module instance, including an entry file.

Complete steps:

  1. Call the require method of the parent module (the parent module refers to the current module of the calling module)
require = function require(path) {
    return mod.require(path);
};
  1. Calling module_ Load method
  2. adoptModule._resolveFilenameGets the path filename of the module
const filename = Module._resolveFilename(request, parent, isMain);
  1. Judge whether there is a cache of the module according to the filename

    • If there is a cache, callupdateChildrenMethod updates the contents of the cache and returns the cache
    • If no cache exists, continue execution
  2. As a native module, callloadNativeModuleMethod

    • If the loading is successful, the native module is returned
    • Otherwise, proceed
  3. Generate a module instance according to the current module name (path) and parent module object:
const module = cachedModule || new Module(filename, parent);
  1. Then judge whether the module is an entry file
if (isMain) {
    process.mainModule = module;
    module.id = '.';
}
  1. Store the instance of the module into the cache of the module
Module._cache[filename] = module;

Detailed explanation of the require () method

  1. An instance of the module calls its ownloadMethod to load the module according to the filename
module.load(filename);
  1. Gets the suffix name of the module file
const extension = findLongestRegisteredExtension(filename);

If the suffix name is in ES module format (. MJS), judge whether the module supports the resolution of. MJS files. If not, throw an exception.

  1. Resolve module file content according to suffix name
Module._extensions[extension](this, filename);
  1. Read file contents according to filename
content = fs.readFileSync(filename, 'utf8');
  1. Compile and execute the read file, and call the module’s own_complilemethod:
module._compile(content, filename);

_compileMain contents and 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;

wrapSafeMethod

Detailed explanation of the require () method

The specific code to obtain the above results is:

const wrapper = Module.wrap(content);
return vm.runInThisContext(wrapper, {
    filename,
    lineOffset: 0,
    displayErrors: true,
    importModuleDynamically: async (specifier) => {
        const loader = asyncESM.ESMLoader;
        return loader.import(specifier, normalizeReferrerURL(filename));
    },
});
  1. Modify the loading status of the module to true
this.loaded = true;
  1. Loading succeeded.

summary

The following conclusions can be drawn from the above commissioning process:

  1. In nodejs, start with the entry file,Everything is a module
  2. Module loading is synchronous.
  3. Due to the existence of the caching mechanism, the circular reference of the module has little impact on the performance, and the circular reference to the module may be incomplete and may lead to errors
  4. The process of the require lookup module is as follows:

Detailed explanation of the require () method

  1. The analysis flow chart of file path is as follows:

Detailed explanation of the require () method

~End of this article~

Learn interesting knowledge, make interesting friends and shape interesting souls!

hello everyone! I am the author of programming SamadhiRecluse KingMy official account is “programming samadhi”. Welcome to pay attention to it. I hope you can give us more advice.

Pay equal attention to knowledge and skills, cultivate both internal and external skills, grasp both theory and practice, and be hard on both hands!

Recommended Today

Hive built-in function summary

1. Related help operation functions View built-in functions: Show functions; Display function details: desc function ABS; Display function extension information: desc function extended concat; 2. Learn the ultimate mental method of built-in function Step 1: carefully read all the functions of the show functions command to establish an overall understanding and impression Step 2: use […]