美文网首页
node的模块加载

node的模块加载

作者: 田成力 | 来源:发表于2019-10-09 20:45 被阅读0次

Node的模块加载

Node的REPL

R:读
E:eval计算
P:写
L:loop

console

标准流 1

  • console.log()
  • console.info()
    错误流2
  • console.warn()
  • console.error()
    测试时间
    console.time('a')
    console.timeEnd('a')
    //TDD测试驱动开发、BDD行为驱动开发,单元测试
    断言
    console.assert()
    如果表达式表达为真就不输出,为假就报错,用于监控
function sun(a,b){
return a+b
}
console.assert(sum(1,2)==3,'报错')

console.dir()
//可以列出对象的的结构
console.trace();
//可以跟踪当前代码的调用栈
//程序执行从上往下执行,栈是先进后出

global全局对象

window里也有全局对象,但是不能直接访问,我们在浏览器里访问global是通过window实现的
1.global的变量是全局变量
2.所有的全局变量都是global的属性
console.log(global)
//chdir:改变目录
//cwd:当前工作目录

  • process当前进程
    process.cwd()
    process.chdir()
    nextTick 把回调函数放在当前执行栈的底部
    setImmediate把回调函数放在事件队列的尾部

回顾 简易版的模块加载


  const fs = require('fs');
  const path = require('path');
  const vm = require('vm')



  class Module {
    constructor(filepath) {
      this.id = filepath;
      this.exports = {};
    }
    load() {
      //读取文件:
      let fileContent = fs.readFileSync(this.id, 'utf8');

      //包装文件
      fileContent = '(function(exports,module,require){' + fileContent + '})';
      let fn = vm.runInThisContext(fileContent);
      fn(this.exports, this, req);
      return this.exports;
    }
  }
  function req(filepath) {

    //文件的路径:
    let absolutepath = path.join(__dirname, filepath);

    let module = new Module(absolutepath);


    //加载模块
    return module.load();

  }

  const a = req('./a.js');
  console.log(a);//hello

升级版

添加对json的处理
添加缓存

    const fs = require('fs');
    const path = require('path');
    const vm = require('vm')

    const ModuleCache = {};
    class Module {
      constructor() {
        this.id = "";
        this.exports = {};
      }


      processFile() {
        return {
          ".js":(filepath)=> {
            let fileContent = fs.readFileSync(filepath, 'utf8');
            fileContent = `(function(module,exports,require,__filename,__dirname){${fileContent}})`;
            let fn = vm.runInThisContext(fileContent);
            fn(this, this.exports, req, filepath, path.dirname(filepath));
          },
          ".json":(filepath)=> {
            let fileContent = fs.readFileSync(filepath, 'utf8');
            this.exports = JSON.parse(fileContent);
          }
        }
      }


      load(filepath) {
        filepath = this.getFileAbsoultePath(filepath);
        this.id = filepath;
        //判断是否缓存过了
        if (ModuleCache[this.id]) {
          //加载过了
          return ModuleCache[this.id].exports;
        }
        let extname = path.extname(filepath);
        this.processFile()[extname](filepath);
        //添加缓存
        ModuleCache[this.id] = this;
        return this.exports;
      }

      getFileAbsoultePath(filepath) {
        //判断是否有后缀名
        //如果有直接使用
        //如果没有 匹配后缀
        if (filepath.indexOf('/') != 0) {
          //传入的是相对路径
          filepath = path.join(__dirname, filepath);
          console.log("filepath===>",filepath);
          
        }
        let extname = path.extname(filepath);
        if (!extname) {
          let canProcessExtnames = Reflect.ownKeys(this.processFile());
          for (let index = 0; index < canProcessExtnames.length; index++) {
            const currentExtname = canProcessExtnames[index];
            filepath += currentExtname;
            if (fs.existsSync(filepath)) {
              //找到文件了
              break;
            } else {
              filepath = null;
            }
          }
        } else {
          //自带了后缀名
          if (!fs.existsSync(filepath)) {
            throw new Error("not find file");
          }
        }
        if (filepath) {
          return filepath;
        }
        throw new Error('not find file')

      }
    }

    function req(filepath) {
      let module = new Module();
      return module.load(filepath);
    }

    const a = req("./a");
    console.log(a);//hello

exports 和 module.exports的关系


console.log(exports===module.exports);//true

// 实际上的形参 和实参 是这样的
let fn=function(module,exports,require,__filename,__dirname){xxxx}

fn(module,module.exports,require,xx,xx);

//可以看到 exports就是module的属性

//但问题是 为什么不能写成
//a.js文件

exports 'hello'

//根据关系我们可以模拟出下面的代码
var obj={arr:[1,2,3]}
var arr=obj.arr;
arr=[4,5,6]

// 这时候的arr和obj.arr还相同吗
// 我们用obj.arr能用到[4,5,6]吗

模块的加载顺序

文件模块

  1. 通过文件的路径找对应的文件 如果文件存在,则加载文件
  2. 如果文件不存在,则找同名文件夹/index.js文件

第三方模块

  1. 通过名称在自己的目录的node_modules中找对应的文件夹
  2. 找到该文件夹下的package.json文件中的main字段对应的文件加载文件
  3. 如果没有package.json 或是没有main字段,则会默认找文件夹下的index.js或index.json文件并加载
  4. 如果还找不到,则再向上一层查找node_modules文件夹

内置模块

  1. 通过名称引用 优先引用

相关文章

  • Node.js 核心模块概述

    模块加载原理与加载方式 Node 中的模块:核心模块/原生模块:Node提供的模块。文件模块:用户编写的模块。 N...

  • app.js初始版

    加载express模块 加载模板 //加载数据库模块 创建app应用,node -> http.createSev...

  • node 模块加载和webpack resolve

    node 模块加载和webpack resolve node module webpack resolve nod...

  • Nodejs的自定义模块加载中的坑

    加载自定义模块有两种方式: 按文件路径加载模块 通过查找node_modules目录加载模块 按文件路径加载 这种...

  • Node模块原理0926

    Node模块原理 1.node模块原理分析 js代码 2.node模块加载分析(多看几遍视频) 3.自己实现一下(...

  • 第6天笔记 nodejs 模块-1

    模块 Node 有简单的模块加载系统。在 Node 里,文件和模块是一一对应的。下面例子里,foo.js加载同一个...

  • Node 面试题整理

    1:简述require()模块加载机制 答:在node中文件即模块,分为原生模块和3种文件模块。具体加载顺序如下图...

  • koa加载解析记录

    1、nodejs下的require, 一切node模块的加载都是从node_modules开始的,打开koa模块p...

  • 使用nodejs实现静态服务器与用到的方法

    添加node内置模块,通过require加载: 整个底层服务器是由node提供的http模块实现的。 创建serv...

  • node的模块加载

    模块实现 依照CommonJS的模块规范,使用require()引入模块的api,使用exports导出模块的方法...

网友评论

      本文标题:node的模块加载

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