NodeJS实现require模块
根据require模块实现流程步骤自实现require模块
NodeJS-require模块系统实现流程
内部实现了一个require方法
function require(path) { return self.require(path); }
通过Module对象的静态__load方法加载模块文件
Module.prototype.require = function(path) { return Module._load(path, this, /* isMain */ false); };
通过Module对象的静态_resolveFilename方法,得到绝对路径并添加后缀名
var filename = Module._resolveFilename(request, parent, isMain);
根据路径判断是否存在缓存,若不存在则创建一个新的Module对象并缓存起来
var cachedModule = Module._cache[filename]; if (cachedModule) { return cachedModule.exports; } var module = new Module(filename, parent); Module._cache[filename] = module; // id是绝对路径 function Module(id, parent) { this.id = id; this.exports = {}; }
利用tryModuleLoad方法加载模块
tryModuleLoad(module, filename);
取出模块后缀
var extension = path.extname(filename);
根据不同后缀查找不同方法并执行对应的方法,加载模块
Module._extensions[extension](this, filename);
是JSON就转换成对象
module.exports = JSON.parse(internalModule.stripBOM(content));
是JS就包裹一个函数
var wrapper = Module.wrap(content); NativeModule.wrap = function(script) { return NativeModule.wrapper[0] + script + NativeModule.wrapper[1]; }; NativeModule.wrapper = ['(function (exports, require, module, __filename, __dirname) { ','\n});'];
执行包裹函数之后的代码,拿到执行结果(String -- Function)
var compiledWrapper = vm.runInThisContext(wrapper);
利用call执行fn函数,修改module.exports的值
var args = [this.exports, require, module, filename, dirname]; var result = compiledWrapper.call(this.exports, args);
返回module.exports
return module.exports;
- 接下来自实现require模块
- 1.js:
console.log(123);
Nhwrequire.js:
const path = require("path"); const fs = require("fs"); const vm = require("vm"); class NJModule { constructor(id) { this.id = id; // 保存当前模块的绝对路径 this.exports = {}; } } // 保存新的Module对象 NJModule._cache = {}; NJModule.wrapper = ['(function (exports, require, module, __filename, __dirname) { ', '\n});']; NJModule._extensions = { ".json": function (module) { let json = fs.readFileSync(module.id); //将JSON转换成对象,存入exports中 let obj = JSON.parse(json); module.exports = obj; }, ".js": function (module) { //根据文件路径读取文件数据 let script = fs.readFileSync(module.id); //包裹成类型为字符串的函数 let wrapper = NJModule.wrapper[0] + script + NJModule.wrapper[1]; //执行包裹函数之后的代码,拿到执行结果(String -- Function) let compiledWrapper = vm.runInThisContext(wrapper); //利用call执行fn函数 compiledWrapper.call(module.exports, module.exports); } }; function NhwRequire(filePath) { //1.将传入的相对路径转换成绝对路径 let absPath = path.join(__dirname, filePath); //2.根据路径判断是否存在缓存,若不存在则创建一个新的Module对象并缓存起来 let cachedModule = NJModule._cache[absPath]; if (cachedModule) { return cachedModule.exports; } let module = new NJModule(absPath); NJModule._cache[absPath] = module; //3.利用tryModuleLoad方法加载模块 tryModuleLoad(module); //4.返回module.exports return module.exports; } function tryModuleLoad(module) { //1.取出模块后缀 let extName = path.extname(module.id); //2.根据不同后缀查找不同方法并执行对应的方法,加载模块 NJModule._extensions[extName](module); } let aModule = NhwRequire("./1.js"); // console.log(aModule);