Node模块加载导出机制

作者: xdoer | 来源:发表于2019-05-17 12:19 被阅读1次

Node中的每一个文件模块都是对象。根据require中传入文件名或者地址,查找缓存,内置模块,找不到时,会创建一个包含filename属性的Module实例。根据判断文件后缀为js时,调用函数找到并读取文件,调用编译函数。我们编写的模块在编译函数的示例代码中的compiledWrapper中执行.

function Module(id, parent) {
  this.id = id;
  this.exports = {};
  this.parent = parent;
  if (parent && parent.children) {
    parent.children.push(this);
  }
  this.filename = null;
  this.loaded = false;
  this.children = [];
}


//导出当前模块
module.exports = Module;

//require方法,用于获取需要的文件
Module.prototype.require = function(path) {
  return Module._load(path, this);
};

//加载需要的文件
Module.prototype.load = function(filename) {
    //判断文件扩展名
  var extension = path.extname(filename) || '.js';
  if (!Module._extensions[extension]) extension = '.js';
  //调用处理函数
  Module._extensions[extension](this, filename);
  this.loaded = true;
};

//扩展名为js的文件处理
Module._extensions['.js'] = function(module, filename) {
  var content = fs.readFileSync(filename, 'utf8');
  module._compile(stripBOM(content), filename);
};


//编译
Module.prototype._compile = function(content, filename) {
//这里的this指的是在Module_.load中创建的包含filename和loaded的Module对象实例module
  var self = this;
  //这里要注意这几个参数
  //self.exports是空对象
  var args = [self.exports, require, self, filename, dirname];
  return compiledWrapper.apply(self.exports, args);
};


Module._load = function(request, parent, isMain) {

  //  计算绝对路径
  var filename = Module._resolveFilename(request, parent);

  //  如果有缓存,取出缓存
  var cachedModule = Module._cache[filename];
  if (cachedModule) {
    return cachedModule.exports;

  // 是否为内置模块
  if (NativeModule.exists(filename)) {
    return NativeModule.require(filename);
  }

  // 生成模块实例,存入缓存
  var module = new Module(filename, parent);
  Module._cache[filename] = module;

  // 加载模块
  try {
    module.load(filename);
    hadException = false;
  } finally {
    if (hadException) {
      delete Module._cache[filename];
    }
  }

  // 输出模块的exports属性
  return module.exports;
};


var compiledWrapper = function(exports,require,module,_filename,_dirname){
  ---------------------------------------
    //我们编写的模块
    var math = require('mvc.html');
    //require返回模块的exports属性,可使用上面挂载的函数属性
    exports.area = function(){
      return math.PI*3*3;
    }


  ---------------------------------------
}

参考:

1、阮一峰《require()源码解读》

http://www.ruanyifeng.com/blog/2015/05

/require.html#comment-349814

2、朴灵《深入浅出NodeJS》

相关文章

  • Node模块加载导出机制

    Node中的每一个文件模块都是对象。根据require中传入文件名或者地址,查找缓存,内置模块,找不到时,会创建一...

  • Node 面试题整理

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

  • 饿了吗大前端阅读(二)

    模块 模块机制 模块加载机制官方文档已经说的很明白的,基本的流程是 如果加载为第三方或者系统依赖(就是在node_...

  • node模块加载机制

    Node中存在一个module对象代表模块自身,拥有一个exports属性,一个文件就是一个模块。 每个js文件可...

  • 那些年成为node攻城狮的路(二)

    模块加载机制浅析 node中模块分为核心模块和文件模块两大类,核心模块诸如fs、http、util...,文件模块...

  • 01-Node 基础使用

    Node 基础使用Node 介绍Node 模块化开发模块成员的导出模块成员的导入Node 系统模块 path 和 ...

  • Node的模块之fs,readline,url

    node的模块 require:导入一个模块 exports:导出模块 module.exports:导出模块 代...

  • Node.js模块以及模块加载机制

    Node.js中的模块 在Node.js中,以模块为单位划分功能,通过一个完整的模块加载机制使得开发人员可以将应用...

  • Node.js 核心模块概述

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

  • JS模块_require,new机制_this机制

    代码模块,导出对象 我们所有的代码不能都写到一个文件里面,如何分开文件? js--> 模块机制; js 加载代码的...

网友评论

    本文标题:Node模块加载导出机制

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