分析模块加载的流程
- 1.加载模块 Module._load 加载模块之后 最终返回的就是module.exports
- 2.Module._resolveFilename 解析文件名, 产生一个可读取的文件名 .js? .json?
- 3.Module._cache 如果文件被缓存过 直接拿上一次的返回结果
- 4.如果模块没有加载过,会根据路径创建一个模块 new Module() {id:文件名,exports:导出结果}
- 5.缓存模块为了后续使用
- 6.module.load 加载模块(读文件)
- 7.获取扩展名来调用不同的加载方式
- 8.根据扩展名查找 对应的加载方式 Module._extension
- 9.js的模块主要是读取
- 10.读取文件后包裹函数 , 并且传入五个参数 [ ‘exports’,‘require’,‘module’,‘__filename’, ‘__dirname’ ]
- 11.执行函数 用户会给module.exports 赋予值
-
- 因为最终返回的是module.exports 所以可以拿到最终的返回结果
const fs = require('fs');
const path = require('path');
const vm = require('vm');
function Module(id) {
this.id = id;
this.exports = {};
}
Module._cache = {};
Module._extensions = {
".js"(module) {
const content = fs.readFileSync(module.id, "utf8");
const wrapperFn = vm.compileFunction(content, [
"exports",
"require",
"module",
"__filename",
"__dirname",
]);
const exports = module.exports;
const thisValue = exports;
const dirname = path.dirname(module.id);
Reflect.apply(wrapperFn, thisValue, [
exports,
myRequire,
module,
module.id,
dirname,
]);
},
".json"(module) {
const content = fs.readFileSync(module.id, "utf8");
module.exports = JSON.parse(content);
},
};
Module._resolveFilename = function (id) {
const fileUrl = path.resolve(__dirname, id);
if (fs.existsSync(fileUrl)) return fileUrl;
const exts = Reflect.ownKeys(Module._extensions);
for (let i = 0; i < exts.length; i++) {
const fileUrl = path.resolve(__dirname, id + exts[i]);
if (fs.existsSync(fileUrl)) return fileUrl;
}
throw new Error("Module not found");
};
Module.prototype.load = function (filename) {
const ext = path.extname(filename);
Module._extensions[ext](this);
};
function myRequire(id) {
const filepath = Module._resolveFilename(id);
const cacheModule = Module._cache[filepath];
if (cacheModule) {
return cacheModule.exports;
}
const module = new Module(filepath);
Module._cache[filepath] = module;
module.load(filepath);
return module.exports;
}
const content = myRequire("./module.json");
console.log(content);