require 源码大致过程
mod.require会默认调用 require 语法Module.prototype.require模块的原型上有 require 方法Module._load调用模块的加载方法,最终返回的是module.exportsModule._resolveFilename解析文件名,将文件名变成绝对路径,默认尝试添加.js .json等Module._cache默认会判断是否存在缓存new Module创建模块(对象),里面有 id,exportsModule._cache[filename] = module把模块缓存起来,方便下次使用module.load尝试加载模块module.paths第三方模块查找的路径Module._extensions[extension]获取当前模块的拓展名,策略是根据拓展名调用对应的方法fs.readFileSync读取文件的内容module._compile去除文本文件 BOM 头,编译文件的内容Module.wrap将用户的内容包裹到一个函数中(function (exports, require, module, __filename, __dirname) { }),用vm.runInThisContext创建沙箱环境,将字符串变成函数执行
简单实现一个自己的 require 去加载 json 文件
新建一个 a.json 文件
{
"name": "kaimo313"
}
const path = require("path");
const fs = require("fs");
function Module(id) {
this.id = id;
this.exports = {};
}
// 加载策略
Module._extensions = {
".js": function () {},
".json": function (module) {
console.log("json---->", module);
// 同步读取
let content = fs.readFileSync(module.id);
module.exports = JSON.parse(content);
}
};
// 把文件名变成绝对路径
Module._resolveFilename = function (filepath) {
let filePath = path.resolve(__dirname, filepath);
let exists = fs.existsSync(filePath);
if (exists) return filePath;
// 尝试添加后缀
let keys = Object.keys(Module._extensions);
for (let i = 0; i < keys.length; i++) {
let currentPath = filePath + keys[i];
if (fs.existsSync(currentPath)) {
return currentPath;
}
}
};
// 获取文件的后缀名进行加载
Module.prototype.load = function (filename) {
let extname = path.extname(filename);
Module._extensions[extname](this);
};
// 加载模块
Module._load = function (filepath) {
let filename = Module._resolveFilename(filepath);
console.log("filename---->", filename);
// 进行模块的创建
let module = new Module(filename);
// 模块加载
module.load(filename);
return module.exports;
};
// 自己实现的 require 方法
function kaimoRequire(filepath) {
// 加载模块
return Module._load(filepath);
}
// 测试
let k = kaimoRequire("./36/a");
console.log("测试 kaimoRequire 输出 k---->", k);



















