nodejs Module加载机制


加载文件类型

node中的文件和模块是一一对应的。一个node.js文件就是一个模块,但是这个文件可能是js代码,JSON或者编译过的C/C++拓展


加载流程图

加载顺序和流程如下图所示,已经加载过的文件会直接缓存起来,下次再require会直接从缓存加载。
在这里插入图片描述

加载文件详细过程

  1. 如果 X 是内置模块
    a. 返回内置模块
    b. 停止执行
  2. 如果 X 以 ‘/’ 开头
    a. 设置 Y 为文件根路径
  3. 如果 X 以 ‘./’ 或 ‘/’ or ‘…/’ 开头
    a. LOAD_AS_FILE(Y + X)
    b. LOAD_AS_DIRECTORY(Y + X)
  4. LOAD_NODE_MODULES(X, dirname(Y))
  5. 抛出异常 “not found”

LOAD_AS_FILE(X)

  • 如果 X 是一个文件, 将 X 作为 JavaScript 文本载入并停止执行。
  • 如果 X.js 是一个文件, 将 X.js 作为 JavaScript 文本载入并停止执行。
  • 如果 X.json 是一个文件, 解析 X.json 为 JavaScript 对象并停止执行。
  • 如果 X.node 是一个文件, 将 X.node 作为二进制插件载入并停止执行。

LOAD_AS_DIRECTORY(X)

  • 如果 X/package.json 是一个文件,
    a. 解析 X/package.json, 并查找 “main” 字段。
    b. let M = X + (json main 字段)
    c. LOAD_AS_FILE(M)
    d. LOAD_INDEX(M)
  • LOAD_INDEX(X)

LOAD_INDEX(X)

  • 如果 X/index.js 是一个文件, 将 X/index.js 作为 JavaScript 文本载入并停止执行。
  • 如果 X/index.json 是一个文件, 解析 X/index.json 为 JavaScript 对象并停止执行。
  • 如果 X/index.node 是一个文件, 将 X/index.node 作为二进制插件载入并停止执行。

加载module详细过程

  • 查找当前目录下面的node_modules目录
    a. LOAD_AS_FILE(DIR/X)
    b. LOAD_AS_DIRECTORY(DIR/X)
  • 如果没找到,再查询父目录的node_modules目录,直到找到或者到了根目录的node_modules目录(待查询目录在module对象里面的paths数组中)

示例

const demo1 = require('./demoModule/demo');
// ./demoModule/demo => console.log('demo file whitout .js')
// ./demoModule/demo.js => console.log('demo file whit .js')
const demo2 = require('./demoModule/demoWithJson');
// {
//     "memo": "this is json file"
// }
console.log(demo2.memo)
const demo3 = require('./demoModule/demoWithJS');
// ./demoModule/demoWithJS => console.log('demo file whit .js')
// ./demoModule/demoWithJS.json => 
// {
//     "memo": "this is demoWithJS.json"
// }
const demo4 = require('./demoModule');
// ./demoModule/index.js => console.log('this is index.js in demoModule')
const demo5 = require('./demoModule/dirWithPackage');
// ./demoModule/dirWithPackage/main.js => console.log('this is main.js in dirWithPackage')
// ./demoModule/dirWithPackage/package.json 里面的main字段为“main.js”
// const demo6 = require('./demoModule/demoNode');
const demo7 = require('demo')
/*
./node_modules/demo/index.js
// 源码:
console.log('this is index.js in node_modules/demo')
const subDemo = require('subdemo');
const subDemo2 = require('subdemo2');

// subdemo 和 subdemo2所在位置和源码
  ./node_modules/demo/node_modules/subdemo/index.js
   => console.log('this is index.js in ./node_modules/demo/node_modules/subdemo') 
  ./node_modules/subdemo2/index.js
   => console.log('this is index.js in ./node_modules/subdemo2') 
*/

const demo8 = require('demo2')
// ./node_modules/demo2/index.js => console.log('this is index.js in ./node_modules/demo2')
// ./node_modules/demo2.js => console.log('this is demo2.js in ./node_modules')
const subDemo3 = require('subdemo3');
// ../node_modules/subdemo3/index.js
const subDemo4 = require('subdemo4');
// ../../node_modules/subdemo4/index.js
const subDemo5 = require('subdemo5');
// /Users/username/.node_modules/subdemo5.js

输出结果

demo file whitout .js
this is json file
demo file whit .js
this is index.js in demoModule
this is main.js in dirWithPackage
this is index.js in node_modules/demo
this is index.js in node_modules/demo/node_modules/subdemo
this is index.js in node_modules/subdemo2
this is demo2.js in ./node_modules
this is index.js in …/node_modules/subdemo3
this is index.js in …/…/node_modules/subdemo4
this is subdemo5.js in /Users/lifugui/.node_modules

其实,module.paths 里面已经包含了上述这些会去查找的目录以及优先级

// 当前文件目录 /Users/username/Documents/projects/nodeDemo
[ 
  '/Users/username/Documents/projects/nodeDemo/repl/node_modules', // 这个目录是干嘛的?不清楚,实测并不会从这个目录加载module
  '/Users/username/Documents/projects/nodeDemo/node_modules',
  '/Users/username/Documents/projects/node_modules',
  '/Users/username/Documents/node_modules',
  '/Users/username/node_modules',
  '/Users/node_modules',
  '/node_modules',
  '/Users/username/.node_modules', // 全局module 可以考虑放这两个目录
  '/Users/username/.node_libraries'
]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值