美文网首页
实现简易版commonjs规范-------require方法

实现简易版commonjs规范-------require方法

作者: 成熟稳重的李先生 | 来源:发表于2019-10-22 18:01 被阅读0次

    commonjs是服务端的js,每个文件就是一个模块,它有自己独立的作用域,并且不存在异步的情况,commonjs提供了一个方法 require,它可以同步的将依赖引入,下边我们来仿写一个require函数,达到同步引用文件的效果

    let path = require("path");
    let vm = require("vm");   // 提供一个沙箱环境,不受外部变量的影响
    let fs = require("fs");
    
    function req(filename){
      let absPath = path.resolve(__dirname, filename);  // 获取文件绝对路径
      let index = 0;
      // let 
      let extnames = Object.keys(Module._extensions);  //获取后缀“池”
      let old = absPath;  // 保存路径名(可能不带后缀)
      if(Module._cache[absPath]){   // 如果请求过这个文件,那么缓存起来,下次直接拿缓存
        return Module._cache[absPath].exports;
      }
      function find(filename) {  // 格式化生成一个准确的路径(即加上“.js”或者“.json”后缀)
        if(index === extnames.length){
          return filename;
        }
        try {
          fs.accessSync(filename);   // 是否有这个文件(如果没有,则会跳入catch中)
          return filename; // 有就返回这个格式化后的路径
        }catch(ex){
          return find(old+extnames[index++]);
        }
      }
      absPath = find(absPath);  // 格式化路径
      try {
        fs.readFileSync(absPath);   // 判断是否有这个文件
      }catch(ex){
        throw new Error("文件不存在");
      }
      let module = new Module(absPath);
      Module._cache[module.id] = module;  // 将这个模块缓存起来
      tryModuleLoad(module);  // 加载它(即执行module.exports赋值操作)
      return module.exports;
    }
    function Module(pathname){
      this.id = pathname;
      this.exports = {};
    }
    function tryModuleLoad(module) {
      let extname = path.extname(module.id);
      Module._extensions[extname](module);
    }
    Module._cache = {};
    Module.wrap = ["(function(exports, module, require, __filename, __dirname){",
    "})"]   // 工具数组,与要引入的文件合并成一个函数
    Module._extensions = {
      ".js"(module) {
        let content = fs.readFileSync(module.id);
        let fnStr = Module.wrap[0] + content + Module.wrap[1];
        let fn = vm.runInThisContext(fnStr);
        fn.call(module.exports, module.exports, module, req);
      },
      ".json"(module) {
        let content = fs.readFileSync(module.id);
        module.exports = JSON.parse(content);
      }
    }
    

    相关文章

      网友评论

          本文标题:实现简易版commonjs规范-------require方法

          本文链接:https://www.haomeiwen.com/subject/fvpxvctx.html