参考文章: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);
}

chenwl
117 声望5 粉丝

平坦的路面上曲折前行