CommonJS
- 模块引用
var math = require('math');
模块定义
- 上下文提供 exports 对象用于导出当前模块的方法或者变量,并且是唯一导出的出口
- 模块中,还存在一个 module 对象,代表模块自身, exports 是 module 的属性
- Node 中,一个文件就是一个模块
// math.js
exports.add = function () {
var sum = 0,
i = 0,
args = arguments,
l = arguments.length;
while (i < l) {
sum += args[i++];
}
return sum;
};
模块标识
- 传递给
require()
的参数,必须是符合小驼峰命名的字符串,或者 以.
或..
开头的相对路径 或 绝对路径,结尾可以没有文件名后缀
- 传递给
模块实现
实现
- 路径分析
- 文件定位
- 编译执行
分类
- 核心模块,Node 提供(核心模块在 Node 源代码编译过程中,编译进了二进制执行文件,在 Node 进程启动时,部分核心模块就直接被加载进内存中,加载速度快)
- 文件模块,用户编写(在运行时动态加载,需要完成的路径分析、文件定位、难以执行过程,加载速度慢)
- 优先缓存加载
路径分析和文件定位
模块标识符分析
- 核心模块,最快
- 路径形式的文件模块,较慢
- 自定义模块(如文件或包),查找费时,最慢
文件定位
- 文件扩展名分析(不含扩展名时,按
.js
、.node
、.json
次序补足,加上扩展名会加快速度) 目录分析和包
- 没有找到对应文件但发现一个目,会按照包处理
- 文件扩展名分析(不含扩展名时,按
模块编译
.js
文件 通过 fs 模块同步读取文件后编译执行.node
文件 C/C++ 编写的扩展文件,通过 dlopen() 方法加载最后编译生成的文件.json
文件 通过 fs 模块同步读取后,用 JSON.parse() 解析返回结果- 其余扩展名文件,都按
.js
文件载入
// 一个正常的 JavaScript 文件会被包装成如下
(function (exports, require, module, __filename, __dirname) {
var math = require('math');
exports.area = function (radius) {
return Math.PI * radius * radius;
};
});
包与 npm
包结构
package.json
包描述文件bin
用于存放可执行二进制文件的目录lib
用于存放 JS 代码的目录doc
用于存放文档的目录test
用于存放单元测试的代码
包描述文件与 NPM
CommonJS 为 package.json 定义的必需字段
- name
- description
- version
major.minor.revision
参考 semver.org - keywords
- maintainers
- contributors
- bugs
- licenses
- repositories
- dependencies
- homepage
- os
- cpu
- engine
- builtin
- directories
- implements
- scripts
npm 新增字段
- author
- bin
- main
- devDependencies
前后端共用模块
- AMD (CommonJS 模块规范的一个延伸)
// define(id?, dependencies?, factory);
define(function() {
var exports = {};
exports.sayHello = function() {
alert('Hello from module ', module.id);
};
return exports;
});
- CMD 规范
// define(factory);
define(function(require, exports, module) {
// The module code goes here
});
- 兼容多种模块规范
;(function (name, definition) {
// 检测上下文环境是否为 AMD 或 CMD
var hasDefine = typeof define === 'function',
// 检查上下文环境是否为 Node
hasExports = typeof module !== 'undefined' && module.exports;
if (hasDefine) {
// AMD 环境或 CMD 环境
define(definition)
} else if (hasExports) {
// 定义为普通 Node 模块
module.exports = definition();
} else {
// 将模块的执行结果挂在 window 中
this[name] = definition();
}
})('hello', function() {
var hello = function() {};
return hello;
});