# CommonJS 的模块规范
- 内容
- 模块
- 二进制
- buffer
- 字节集编码
- I/O流
- 进程环境
- 文件系统
- 套接字
- 单元测试
- web服务器网关接口
- 包管理
# 1.模块的定义
- 上下文提供
require()
方法来引入外部模块 - 对应功能,上下文提供
exports
对象用于导出当前模块的方法或变量,也是唯一出口 - 模块中存在
module
对象, 代表模块本身 exports
是module
属性module.exports
exports
// math.js
exports.add = function() {
var sum = 0,
i = 0,
args = arguments,
l = args.length;
while(i < l) {
sum += args[i++];
}
return sum;
}
# 2.模块的使用
# require()
- 符合小舵峰命名
- 可以没有文件后缀名
// program.js
var math = require('math')
var val = math.add(12, 23, 43)
console.log(val)
# 3.node 的模块实现
- 引入,经历三个步骤
- 路径分析
- 文件定位
- 编译执行
# 核心模块和文件模块
# 优先从缓存加载
- 核心模块
- 在node源代码编译过程中,编译进了二进制文件
- node启动时,直接加载进内存中
- 核心模块使用时省略 文件定位 编译执行
- 文件模块
- 运行时动态加载
# 路径分析
# 模块标识符分析
- 核心模块 --> 名称查找
- 自定义模块 --> 路径分析查找
# 文件定位
- 文件扩展名
- 查找优先级 .js > .json > .node (一般不是js后缀 要加上)
- 目录分析和包
- 如果是一个目录 当作包来处理
- node在当前的目录下查找 package.json
- 通过 JSON.parse()解析包描述对象
- 得到 main属性指定的文件名进行定位
- 默认文件名 index.js > index.json > index.node
# 编译执行
- 文件模块都是一个对像
- 定位到具体的文件后, 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
# 核心模块
- 两部分
- C/C++编写 存放在 Node项目的src目录下
- JavaScript编写 存放在 Node项目的lib目录下
# 内建模块导出
- 文件模块 <---- 核心模块(JavaScript) <----- 内建模块(C/C++)
- Node 在启动的时候,会生成一个全局变量 process, 并提供 Binding()方法协助加载内建模块
# 核心模块的引入流程
5. require('os')
4. NativeModule.require('os')
3. process.binding('os')
2. get_builtin_module('node_os')
1. NODE_MODULE(node_os, reg_func)