Open wenjinhua opened 3 years ago
CommonJS规范为JavaScript制定了一个美好的愿景——希望JavaScript能够在任何地方运行。
CommonJS对模块的定义十分简单,主要分为模块引用、模块定义和模块标识3个部分。
var math = require('math');
exports.add = function() {}
node在实现中并非完全按照connonjs规范,而是对模块规范进行了一定的取舍,同时增加了少许自身的特性。
1. 在node中引入模块需要经历如下3个步骤:
2. node中,模块分为以下两类:
以下为详细的模块加载过程:
因为标识符有几种形式,所以对于不同的标识符,模块的查找和定位有着不同程度的差异。模块分类如下:
1. 核心模块 核心模块的优先级仅次于缓存加载,它在node源代码编译过程中被编译成了二进制文件,加载速度最快。
2. 路径形式的文件模块 require会将路径转化为真实路径,并以真实路径作为索引,将编译执行后的结果放到缓存中,以使二次加载更快。
3. 自定义模块 node会逐个尝试模块路径中的路径,直到找到目标文件为止。
1. 文件扩展名的分析:当传递给require的标识符不包括文件扩展名时,node会按照以下次序补足扩展名,依次尝试:
在尝试的过程中,node会调用fs模块同步阻塞式的判断文件是否存在。因为node是单线程的,所以这里是一个会引发性能问题的地方。(解决:在引入.json和.node文件时,加上扩展名)
2. 目录和包的处理:require通过分析文件扩展名后,可能得到的是一个目录,此时node会将目录当做一个包来处理。
定位到具体的文件后,node会新建一个模块对象,然后根据路径载入和编译。对于不同的扩展名,其载入方式如下:
注:每个编译成功的模块,都会将其文件路径作为索引缓存在Module._cache对象上,以提高二次引入的性能
1. js模块的编译 node对获取的js文件进行了头尾的包装,包装后的代码会通过vm原生模块的runInThisContext()执行
(function(exports, requiure, module, __filename, __dirname){ ... }
2. c/c++模块的编译 node调用process.dlopen()进行加载和执行,(dlope在windows和*nux平台通过libuv进行了兼容).node模块并不需要编译,因为他是编写c/c++模块之后编译生成的。
3. json文件的编译
1. 内建模块
1. 模块机制
1.1 commonjs规范
CommonJS规范为JavaScript制定了一个美好的愿景——希望JavaScript能够在任何地方运行。
CommonJS对模块的定义十分简单,主要分为模块引用、模块定义和模块标识3个部分。
1.2 node的模块实现(node中引入模块的过程)
node在实现中并非完全按照connonjs规范,而是对模块规范进行了一定的取舍,同时增加了少许自身的特性。
1. 在node中引入模块需要经历如下3个步骤:
2. node中,模块分为以下两类:
以下为详细的模块加载过程:
1.2.1 优先从缓存中加载
1.2.2 路径分析
因为标识符有几种形式,所以对于不同的标识符,模块的查找和定位有着不同程度的差异。模块分类如下:
1. 核心模块 核心模块的优先级仅次于缓存加载,它在node源代码编译过程中被编译成了二进制文件,加载速度最快。
2. 路径形式的文件模块 require会将路径转化为真实路径,并以真实路径作为索引,将编译执行后的结果放到缓存中,以使二次加载更快。
3. 自定义模块 node会逐个尝试模块路径中的路径,直到找到目标文件为止。
1.2.3 文件定位
1. 文件扩展名的分析:当传递给require的标识符不包括文件扩展名时,node会按照以下次序补足扩展名,依次尝试:
在尝试的过程中,node会调用fs模块同步阻塞式的判断文件是否存在。因为node是单线程的,所以这里是一个会引发性能问题的地方。(解决:在引入.json和.node文件时,加上扩展名)
2. 目录和包的处理:require通过分析文件扩展名后,可能得到的是一个目录,此时node会将目录当做一个包来处理。
1.2.4 模块编译
定位到具体的文件后,node会新建一个模块对象,然后根据路径载入和编译。对于不同的扩展名,其载入方式如下:
注:每个编译成功的模块,都会将其文件路径作为索引缓存在Module._cache对象上,以提高二次引入的性能
1. js模块的编译 node对获取的js文件进行了头尾的包装,包装后的代码会通过vm原生模块的runInThisContext()执行
2. c/c++模块的编译 node调用process.dlopen()进行加载和执行,(dlope在windows和*nux平台通过libuv进行了兼容).node模块并不需要编译,因为他是编写c/c++模块之后编译生成的。
3. json文件的编译
1.3 核心模块
1.3.1 js核心模块的编译过程
1.3.2 c/c++核心模块的编译过程
1. 内建模块
1.3.3 核心模块的引入流程
1.4 c/c++扩展模块