模块机制
1. CommonJS
1. 模块规范
a. 模块引用
- 在CommonJS中,存在require()方法,接收模块标识,以此引入一个模块的API到当前模块中。
b. 模块定义
- 对应引入功能,上下文提供了exports对象用于导出当前模块的方法或者属性,并且是唯一的出口。
- 在模块中,module对象代表模块自身,而exports是module的属性。
- 在Node中,一个文件就是一个模块,将方法挂载在exports对象上作为属性即可定义导出的方式。
c. 模块标识
- 模块标识其实就是传递给require()方法的参数,它必须是小驼峰命名法的字符串,可以没有后缀.js。
CommonJS构建的这套模块导出和引入机制使得用户无需考虑全局污染的问题。
2. Node的模块实现
-
Node在引入模块时需要经历如下三个步骤:
-
路径分析
-
文件定位
-
编译执行
-
-
Node的模块分为两类:核心模块和用户自定义的文件模块。
-
核心模块在Node源代码编译过程中已经被编译进了二进制的执行文件。在Node进程启动时,部分核心模块就直接被加载进内存中,所以这部分核心模块引入时可以省略前两个步骤,加载速度是最快的。
-
文件模块实在运行时动态加载,需要完整地经历上面三个步骤,速度比加载核心模块慢。
2.1 优先从缓存加载
- Node对引入过的模块都会进行缓存,以减少第二次引入时的开销。
- Node缓存的时编译和执行后的对象。
- 不论是核心模块还是文件模块,require方法对相同模块的二次加载都采用缓存优先的方式,这是第一优先级的。且核心模块的缓存检查优先于文件模块。
2.2 路径分析
-
核心模块
- 核心模块的优先级仅次于缓存加载,在Node的源代码编译过程中已经编译进了二进制代码,加载过程最快。
- 如果文件模块的标识符与核心模块相同,如果试图加载之是不会成功的。解决方法可以采用路径引入。
-
路径形式的文件模块
-
在分析文件模块时,require方法会将路径转化为真实路径,以真实路径为索引,将编译执行后的结果存放到缓存中,以使第二次加载更加迅速。
-
由于指定了路径,查找过程中可以节约大量的时间。
-
-
自定