English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Simple Simulation of the Loading Mechanism of require in node.js

Firstly, let's understand the loading mechanism of require in nodejs

1require's file loading order

The extension name can be omitted when loading files with require:

          require('/module');

     // At this time, the file is executed as a JS file

          require('/module.js');

     // At this time, the file is parsed as a JSON file

          require('/module.json');

     // At this time, the precompiled C++ Module execution

          require('/module.node');

     // Load the file pointed to by main in the package.json of the directory module

          require('/module/default.js');

     // Load the index.js file in the directory module

     Through ./ Or ../ Starting with: it searches for the module from the folder where the current file is located according to the relative path;

         require('../file.js'); => Look for file.js file in the parent directory

     Through / Starting with: it starts the search from the system root directory to find the module;

          require('/Users/iceStone/Documents/file.js'); => Search for it with an absolute path, no objections

     If the parameter string does not start with “./Or/Starting with “”, it indicates that a default provided core module (located in Node's system installation directory) is being loaded:

          require('fs'); => Load the file system module from the core modules

     Or search for files in the node_modules directory from the current directory upwards:

          require('my_module'); => Search for my_module.js file in the node_modules folders at all levels;

     If require is passed a directory path, it will automatically check the package.json file in the directory, then load the entry file specified by the main field

     If the package.json file does not have a main field, or there is no package.json file at all, the default index.js file in the directory is used as the module:

          require('/calcuator'); => Look for the index.js file in the calculator directory under the current directory

2require cache

     When Node loads a module for the first time, it caches the module. For subsequent loads of the same module, it directly retrieves the module's module.exports property from the cache (the module is not executed again).

     If you need to execute the code in the module multiple times, you can generally expose behavior (function) of the module, and the module cache can be obtained through require.cache, and it can also be deleted

3All code runs in the module scope and does not pollute the global scope.

Second, simulate the require function

The internal loading of require is relatively complex, let's simulate a simple loading below

The simple implementation mechanism of require is:

     Find the corresponding module file for the passed module id through the loading rules

     Read the code inside this file

     Build a private space for this segment of code through concatenation

     Execute this code

     Get the return value of module.exports

 nodejs_require.js
 // [Simulated require function]
 "use strict"
 function $require(id) {
 //1first check if the module exists, if it does not exist, then throw 'Can't found file'
 //2if it exists, read the code
 const fs = require('fs');
 const path = require('path');
 // File name
 let filename = id;
 //Check if it is an absolute path
 if (!path.isAbsolute(filename)) {
  filename = path.join(__dirname, id);
 }
 // File directory
 let dirname = path.dirname(filename);
 //Simulate the caching mechanism of require
 $require.cache = $require.cache || {};
 if($require.cache[filename]){
  return $require.cache[filename].exports;
 }
 // Read the module code
 let code="";
 try {
  code = fs.readFileSync(filename,'utf-8'); // Block reading the file, it will not be placed in the event queue 
 } catch (error) {
  console.log(" [*']can't found file! ");
  throw error;
 }
 // console.log(code);
 // 3execute code, the code to be executed needs to create an independent space
 // Define a data container to store the members exported by the module
 let _module = { // Each JS module will have a global module variable
  id:'.',
  exports:{},
  parent:module,
  filename:filename
 };
 let _exports = _module.exports;
 // Create an independent space
 code = `(function($require,module,_exports,__dirname,__filename){
  $[code]
 })($require,_module,_exports,dirname,filename)`;
 // Execute code
 eval(code);
 // Cache
 $require.cache[filename] = _module;
 // Return result
 return _module.exports;
 }
 setInterval(()=>{
  const rr = $require("./test.js");
  console.log(rr);
 },1000);

The two modules used for the above module test

 //test.js
 const date = $require('./date.js');
 console.log(module);
 module.exports = date;
 //date.js
 module.exports = new Date();

Summary

That's all for this article. I hope the content of this article can bring you some help in learning or work. If you have any questions, you can leave a message to communicate.

Statement: The content of this article is from the network, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#w3Please report via email to codebox.com (replace # with @ when sending an email) and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.

You May Also Like