在CommonJS规范中,通过exports或module.exports导出一个模块。模块中存在require()方法,通过这个方法接受模块标识,然后根据node的模块引入规则引入模块。就能在模块使用引入模块的属性和方法了。
在node中引入模块,会经历以下三个步骤:
- 路径分析
- 文件定位
- 编译执行
// app.js
console.log(typeof require); // 输出 function
console.log(require.toString()); /* 输出
function require(path) {
try {
exports.requireDepth += 1;
return mod.require(path);
} finally {
exports.requireDepth -= 1;
}
}
*/
这是输出结果:
可以看出 require 函数接受一个参数 path(模块标识)。然后根据模块标识来进行路径分析和文件定位。
路径分析
- 引入核心模块,比如:
let http = require("http");
- 以"
./
" 或 "../
" 引入的相对路径的模块文件 - 以"
/
" 引入的绝对路径模块 - 以非路径形式引入的模块 比如通过npm下载的模块,配合
package.json
文件引入
文件定位
在node中引入模块时,文件扩展名是可以省略的。node会按照 .js
.node
.json
格式依次去匹配
// json.js
console.log(".js文件");
json.josn文件
{
"name":"鲁班七号"
}
let js = require("./json"); // 输出 .js文件
let json = JSON.stringify(require("./json.json"));
console.log(json); // 输出 {"name":"鲁班七号"}
关于require方法引入模块的步骤如下:
- 查找文件可能存在的文件扩展名: .js .node .josn
- 判断是否是绝对路径
- 判断是否是有目录的后缀
/
- 判断缓存中是否存在,如果存在,就直接加载
- 如果缓存不存在,就遍历所有路径,是否存在该模块
- 如果不存在,判断目录中是否有 package.json 文件
- 是否存在目录名 + index + 后缀名 的文件
- 将找到的文件路径存入缓存
- 没有找到,报错
参考: 《深入浅出Node.js》作者:朴灵 第二章 模块机制