参考文章:CommonJS 标准
剖析
- require 加载模块门路
- module.exports 导出模块~~~~
- 每个模块都是一个沙箱环境,互不烦扰
- 依据文件后缀判断文件解决形式 (json,js)
编写
加载模块 require
function myRequire(moduleRelPath){
// 可能是相对路径,须要 resolve
path.resolve(__dirname,moduleRelPath);
}
Module 类
- 模块
function Module(moduleAbsPath){
this.modulePath = moduleAbsPath;
this.exports = {}}
- 拼接执行字符串
Module.wrapper = ["(function(exports,module,require){","})"
]
- 按文件解决
Module.extension = {".js"(module){},
".json"(module){},}
加载模块
Module.prototype.load = function () {
// 获取文件后缀名
let extname = path.extname(this.modulePath);
// 交给对应办法解决
Module.extension[extname](this);
};
导出
function myRequire(id) {let absPath = path.resolve(__dirname, id);
let module = new Module(absPath);
// 加载模块
module.load();
// 导出
return module.exports;
}
解析文件
解决 json
Module._extensions[".json"] = (module)=> {let str = fs.readFileSync(module.id, "utf-8");
str = JSON.parse(str);
// 取出内容间接绑定到 module.exports
module.exports = str;
}
解决 js
const vm = require("vm");
Module._extensions[".js"] = (module)=> {let str = fs.readFileSync(module.id, "utf-8");
// 拼接办法
let scriptStr = Module.wrapper[0] + str + Module.wrapper[1];
// 沙箱环境
let fn = vm.runInThisContext(scriptStr);
// 执行并传参
fn.call(module.exports, module.exports, module, myRequire);
}