Node.js的模块机制

模块加载过程:

路径分析 -> 文件定位 -> 模块编译

Node对引入过的模块都会进行缓存,以减少二次引入时的开销。缓存的是编译和执行之后的对象。require时对缓存中的模块是第一优先级的

路径分析

模块标识符:require的参数,按书写形式可以分成以下几类:

  • 核心模块:如http,fs,path
  • 文件模块
    • 路径模块

      • 相对路径模块:.或..开始
      • 绝对路径模块:/开始
    • 非路径形式的模块

核心模块

  • 在Node.js源代码编译过程中就已经编译成二进制代码,加载速度超快;
  • 优先级仅次于缓存,因此与核心模块同标识符的文件模块都不能加载成功。

路径形式的文件模块

  • require时才会进行模块编译和执行;
  • 会转换为真实路径,并且以真实路径作为索引,将编译执行后的对象放到缓存中。

非路径形式的文件模块

  • 从当前模块开始,一直沿路径向上逐级递归,直到根目录,寻找node_modules目录进行文件定位;

文件定位

分析标识符的过程中,先分析文件扩展名,没有查找到对应的文件,但是得到一个目录,就会将该目录当成一个包来处理。

文件扩展名分析

require时的标识符不需要包含文件扩展名,Node会按.js,.json,.node的次序同步定位。

判断文件是否存在是同步进行的,所以.json.node在引入时加上扩展名会加快引入速度

目录分析和包

模块编译

文件模块在定位成功后,Node会新建一个Module对象,然后根据路径载入并编译。根据文件的扩展名不同,其载入的方法也不同。

//Module 对象
function Module(id,parent){
    this.id = id;
    this.exports = {};
    this.parent = parent;
    updateChildren(parent, this, false);
    this.filename = null;
    this.loaded = false;
    this.children = [];
}

可以通过require.extensions知道系统中已有的扩展方式。甚至可以使用require.extensions[‘.ext‘]的形式对.ext扩展名进行自定义加载方式,不过官方不鼓励,建议先编译成JavaScript文件。

.js 文件

通过fs模块同步读取文件后编译执行;

首先会将文件内容进行头尾包装:

(function(exports , require , module , __filename , __dirname){
    **JavaScript content**
});

这样做可以:

  • 在该文件中引入exports , require , module , __filename , __dirname变量;
  • 每个模块文件之间都进行了作用域隔离;

包装之后的模块就会交给vm.runInThisContext执行得到一个function(注意是function)。最后将module.exports,require,module以及在文件定位中得到的 __filename 和 __dirname作为参数传递给这个function执行。

所以嘛,在模块内对exports进行赋值:

exports = function(){};

是改变了匿名函数的形参的引用,但是实参中无论是module还是module.exports都不能知道被赋值了。

.node

这是用C/C++编写的扩展文件,通过dlopen()方法加载最后编译生成的文件。

.json

通过fs模块同步读取文件后,用JSON.parse()解析返回结果,然后将它赋给模块对象的exports。

每一个编译成功的模块都会将其文件路径作为索引缓存在Module._cache对象上,以提高二次引入的性能。

引用:

http://nodejs.cn/

http://www.ituring.com.cn/book/1290

原文地址:https://www.cnblogs.com/bykp/p/8338245.html

时间: 2024-08-23 14:15:38

Node.js的模块机制的相关文章

Node.js之模块机制

文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 其实在JavaScript的发展中,它主要是在浏览器前端中被应用广泛.因为在实际应用中, JavaScript的表现能力主要取决于宿主环境的API支持程度, 在最早期,只有对BOM, DOM的支持,随着HTML5的出现,在浏览器中出现了更多,更强大的API供JavaScript调用,但是这些都是发生在前端,后端JavaScript的规范却远远落后.Java有class文件,Phthon有import机制,P

深入浅出Node.js (2) - 模块机制

2.1 CommonJS规范 2.1.1 CommonJS的出发点 2.1.2 CommonJS的模块规范 2.2 Node的模块实现 2.2.1 优先从缓存加载 2.2.2 路径分析和文件定位 2.2.3 模块编译 2.3 核心模块 2.3.1 JavaScript核心模块的编译过程 2.3.2 C/C++核心模块的编译过程 2.3.3 核心模块的引入流程 2.3.4 编写核心模块 2.4 C/C++扩展模块 2.4.1 前提条件 2.4.2 C/C++扩展模块的编写 2.4.3 C/C++扩

Node.js(二)——模块与包管理工具

http,process等等这些都是模块 一.Node.js的模块与Commonjs规范 1.js的天生缺陷--缺少模块化管理机制 ·表现--JS中容易出现变量被覆盖,方法被替代的情况(既被污染).特别是存在依赖关系时,容易出现错误.这是因为JS缺少模块管理机制,来隔离实现各种不同功能的JS判断,避免它们相互污染. ·解决--经常采用命名空间的方式,把变量和函数限制在某个特定的作用域内,人肉约定一套命名规范来限制代码,保证代码安全运行.jQuery中有许多变量和方法,但是无法直接访问,必须通过j

Node.js 的模块系统

Node.js的模块系统是借鉴 CommonJS 的 Modules 规范实现的,因此,下面我们需要先了解 CommonJS 的 Modules 规范,希望对大家学习Node.js有所帮助. CommonJS 的 Modules 规范 CommonJS 对模块的定义非常简单,主要分为 模块引用.模块定义和模块标识三个部分. 1. 模块引用 - require() 方法 2. 模块定义 - module.exports 对象 3. 模块标识 - 传递给 require() 方法的参数 通过 Com

对Node.js的异步机制的思考

Node.js的异步机制是其最大的特色,异步可以应对高并发,具有很好的性能. 但是如果在某个方法里,涉及到数据库的多层查询,异步机制反而成为阻碍.当执行完第一层SQL后,根据所得的结果集(rows)进行结果集进行遍历时,每次遍历的结果作为where条件再执行下一层SQL时,下一层及以后的SQL并不会执行,而是在结果集(rows)遍历到最后时,才执行下一层SQL. 这时,若SQL只有两三层,其实倒还好,可以合并SQL:但是SQL层数多了之后,这种异步机制却是最大的阻碍.这时,就需要用到Node.j

Node.js文件模块fs监视文件变化

Node.js文件模块fs监视文件变化 Node中文件模块fs监视文件的函数源码如下: fs.watch = function(filename) { nullCheck(filename); var watcher; var options; var listener; if (util.isObject(arguments[1])) { options = arguments[1]; listener = arguments[2]; } else { options = {}; listen

node.js基础模块http、网页分析工具cherrio实现爬虫

node.js基础模块http.网页分析工具cherrio实现爬虫 一.前言      说是爬虫初探,其实并没有用到爬虫相关第三方类库,主要用了node.js基础模块http.网页分析工具cherrio. 使用http直接获取url路径对应网页资源,然后使用cherrio分析. 这里我主要学习过的案例自己敲了一遍,加深理解.在coding的过程中,我第一次把jq获取后的对象直接用forEach遍历,直接报错,是因为jq没有对应的这个方法,只有js数组可以调用. 二.知识点    ①:supera

(译)Node.js的模块-exports和module.exports

原文标题:Node.js Module – exports vs module.exports原文链接:http://www.hacksparrow.com/node-js-exports-vs-module-exports.html exports 和 module.exports 有什么区别? 你一定很熟悉 Node.js 模块中的用来在你的模块中创建函数的 exports 对象,就像下面这样. 创建一个叫做rocker.js的文件: exports.name = function() {

node.js笔记——模块的开发

模块是什么? 简单来说模块是用来将实现某个功能的代码进行封装以便在其他项目中通过简单引入的方式实现模块中封装的功能的一个东西!!(我更想管他叫小程序). 模块的引入 模块的引入使用reqiure()函数来实现例如引入http模块 var h = require("http"); 这里需要注意的是require()加载函数可以加载指定的js文件,当引入的不是某个js文件而是一段没有扩展名的字符时,默认node.js会加载当前根目录下的node_modules文件夹下面的文件夹里的文件 并