模块

common.js模块

     module:代表模块自身

     exports:是module的属性,用于导出当前模块的方法和属性

     require:用于接收一个模块标识引入一个模块

nodejs中模块实现

 node引入模块步骤

1)路径分析

2)文件定位

3)编译执行

node模块分类

1)核心模块:Node提供的模块,在node源代码编译过程中,编译成了二进制文件,在Node进程启动时,部分模块被存在了内存中,所以在引入的时候文件定位和编译执行两个步骤会被省略,而且路径分析也是优先分析,所以这类模块是加载最快的

2)文件模块:用户编写的模块,它是动态加载,路径分析,文件定位,编译执行缺一不可,所以没有核心模块加载的快

缓存

和浏览器缓存相似,node也会对引入过的文件进行缓存,但是缓存的是require模块编译和执行过的文件,不论是核心模块还是文件模块都会优先从缓存中读取文件,核心模块的缓存检查优先于文件模块

路径分析

1)核心模块:如fs,http这类模块加载的速度仅次于缓存加载

2)路径形式文件模块,比如以 ./   /  ../开头的模块标识符,在分析路径形式的文件模块时,先将其转换为真实路径,并以此路径作为索引将编译执行后的结果存放在内存中,以使第二次的加载时间更快。由于指定了模块的具体文件路径,节省了大量时间,其加载速度慢于核心模块

3)自定义模块:既非核心模块又非路径形式的文件模块。这类模块查找起来最费时间,(1)当前文件的node_modules (2)父文件夹的node_modules (3)。。。 (4)根目录的node_modules   文件夹路径越深,查找的时间越长,直到找到文件为止

文件定位

1)文件扩展名分析:标识符中不包含文件扩展名,则通过.js .json .node来依次进行匹配。在尝试的过程中,会通过同步阻塞的方式来判断文件是否存在,会造成性能问题。如果扩展名为.json或.node加上后缀名会提高效率

2)目录分析和包:若文件扩展名分析过程中未分析到文件而分析到了文件夹,则会将这个文件夹当做包来处理

    (1)查找目录packge.json,通过JSON.parse从中取出main属性指定的文件名进行定位,若文件名没有文件扩展名则进入文件名分析阶段

    (2)如果main属性指定的文件名错误或package.json文件不存在,Node会将index作为文件名,分别寻找.js .json .node文件

    (3)若没有定位到文件,则进入下一个模块路径进行寻找,若所有的模块路径数组遍历完都未寻找到,则抛出异常

模块编译

在Node中,每个文件模块都是一个变量,变量定义如下

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 = []
}

在前两步定位到文件之后,会为该文件创建一个模块对象,根据定位到的路径载入文件,载入方式

       .js 通过fs模块同步读取文件后编译文件

       .node这是用c/c++编写的扩展文件,可以通过dlopen方法载入编译后的文件

       .json 通过fs模块同步解析文件后,通过JSON.parse解析返回结果

       其余扩展名,都会被当作.js引入

      对js的编译,一个正常的js文件,会被如下函数包括,然后runInThisContext(类似于eval),返回一个函数,然后通过将当前模块的exports,require,当前模块自身,当前文件名称,当前文件目录传入函数进行执行,然后将exports对象返回给调用者

(function(exports, require, module, __filename, __dirname) {})

包与npm

common包规范:包结构,包描述

包结构: 

package.json

lib

bin

test

doc

包描述:package.json

原文地址:https://www.cnblogs.com/ranjianxi/p/8404544.html