Node中对CommonJS模块规范的实现

版权声明: https://blog.csdn.net/qq_34305040/article/details/80587331

一、首先了解一下CommonJS的模块规范

1.模块引用
   在CommonJS规范中,存在require( )方法,它接受一个模块标识,用来引入一个模块中API

2.模块定义
   既然在模块中有require( )方法来引入外部模块,那么也存在某个方法来导出模块的方法或者变量,对,它就是export对象。在模块中还存在一个module对象,它代表的是模块的本身,而export是module的属性。
   code:

//  method.js
export.add = function(n){
    var sum = 0,i=0;
    while(i<n){
        sum += i;
    }
    return sum;
}

在另一个文件中引入模块并调用定义的属性和方法:

//  use.js
var method = required("method");
export.fn = function(val){
    return method.add(val);
}

3.模块标识
   所谓的模块标识其实就是传递给required( )方法的参数,它有如下的要求:
   (1)它必须是符合小驼峰命名的字符串
   (2)或者是以 ...开头的相对路径,或者绝对路径
   (3)其实它可以没有文件名后缀
   
CommonJS的这套模块导出,引入的机制使得用户完全不必考虑变量污染,命名空间等问题


二、Node模块的实现

Node中的模块分为两大类:1.核心模块 (example:http,fs等等),2.用户定义的文件模块(如上面代码中的method和use模块)

在Node中实现模块分为一下三个步骤:
   (1)路径分析
   (2)文件定位
   (3)编译运行

   在Node进程启动时,部分核心模块直接加载到内存之中,此时文件定位和编译执行两个步骤可以省略,并且在路径分析中优先判断,所以它的加载速度是最快的;而文件模块,是在运行时动态加载,需要完整的路径分析,文件定位,编译执行过程,所以速度比核心模块加载慢很多。

1.优先从缓存中加载
   就像浏览器为了提高前端的性能缓存静态资源一样,Node引入过的模块都会进行缓存,以减少第二次载入时的开销。
   不管是核心模块还是文件模块,require( )对相同的模块的二次加载都采用缓存优先,不同之处在于对核心模块的缓存检查的优先级高于文件模块。

2.路径分析和文件定位
(1)模块标识符分析
   基本的前面我都有提到过,另外除了核心模块和以路径形式的文件模块,这里再补充一种——自定义模块:
   自定义模块值得是非核心模块,也不是路径形式的标识符。它是一种特殊的文件模块,可能是一个文件或者包的形式,这类模块的查找是最费时间的,也是所有引入方式中最慢的一种,因为它需要通过模块路径一次次的尝试搜索,直到找到目标文件为止。

(2)文件定位
   关于文件定位,有一些细节需要注意的:文件扩展名的分析,目录和包的处理。
   1.文件扩展名分析
   在CommonJS规范中允许标识符中不包含文件扩展名,一般这种情况Node会按.js、.node、.json的次序补充扩展名,然后依次查找.
   2.目录分析和包
   在分析标识符的过程中,require( ) 通过分析文件扩展名之后可能并没有找到此文件,但是会的得到一个目录,这种情况经常在引入自定义模块和逐个查找时经常会出现,此时Node会将目录当做一个包来处理。
   首先,Node在当前目录查找package.json(不懂的百度了解一下),通过JSON.parse()解析出包描述对象,从中取出main属性指定的文件名进行定位。而如果main属性指定的文件名错误,或者压根没有package.json文件,Node会将index当作默认文件名,然后按照.js、.node、.json的后缀次序依次查找。
如果在目录分析中没有成功找到任何文件,则自定义模块进入下一个模块路径进行查找。如果模块路径数组被遍历完,还是没有找到目标文件,则会抛出一个查找失败的错误。

3.模块编译
编译执行是引入文件模块的最后一个阶段,找到目标文件之后,Node会新建一个模块对象(每一个文件模块都是一个对象),然后根据路径载入并编译。
每个不同的文件名后缀采用不同的载入方法:
.js ——— 通过fs模块同步读取文件后编译执行 (JS编译的实现
.node ——— 使用C/C++编写的扩展文件
.json ——— 通过fs模块同步读取文件后,用JSON.parse( ) 解析
其余的扩展名文件 ——— 全当作.js载入
了解更多

展开阅读全文

没有更多推荐了,返回首页