分享

一步到位:require()模块加载顺序

 昵称46000165 2017-08-06
本文参考主要来自官网:require.resole()
node中的模块分为两类,一类是核心模块,另一类是文件模块。核心模块是node自身提供的模块,除核心模块外的其他模块都是文件模块,包括第三库提供的模块。
node在加载模块时,会优先从缓存中查找有没有该模块,如果有,直接返回,否则从磁盘(文件模块)或内存(核心模块)中加载。node每次成功加载模块后,会把该模块缓存下来,因为node中加载后的模块,其实是JavaScript对象。缓存的模块以模块文件所在绝对路径为键,exports对象为值(核心模块缓存使用的键到底是不是模块文件名不得而知)。
require方法在加载模块时依据所接受的参数值的不同而行为有所不同,下面翻译一下官方给出   require()加载模块的顺序(伪代码描述):
require(X) from module at path Y
1. If X is a core module,
   a. return the core module//如果x是模块名且是核心模块,则加载核心模块并返回
   b. STOP
2. If X begins with '/'
   a. set Y to be the filesystem root//如果x以‘/’开头,则把Y设为文件系统的根路径,Y是调用require时所在的绝对路劲
3. If X begins with './' or '/' or '../'
   a. LOAD_AS_FILE(Y + X)//以LOAD_AS_FILE算法加载,如果没找到,跳到b
   b. LOAD_AS_DIRECTORY(Y + X)//以LOAD_AS_DIRECTORY算法加载,X被当做包加载。如果没找到,跳到4
4. LOAD_NODE_MODULES(X, dirname(Y))//以LOAD_AS_MODULES算法加载,如果没找到,跳到5
5. THROW "not found" //抛出错误
LOAD_AS_FILE(X) //LOAD_AS_FILE算法
1. If X is a file, load X as JavaScript text.  STOP
2. If X.js is a file, load X.js as JavaScript text.  STOP
3. If X.json is a file, parse X.json to a JavaScript Object.  STOP
4. If X.node is a file, load X.node as binary addon.  STOP
LOAD_INDEX(X)//LOAD_AS_INDEX算法
1. If X/index.js is a file, load X/index.js as JavaScript text.  STOP
2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
3. If X/index.node is a file, load X/index.node as binary addon.  STOP
LOAD_AS_DIRECTORY(X)//LOAD_AS_DIRECTORY算法,X是包名
1. If X/package.json is a file,
   a. Parse X/package.json, and look for "main" field.//查找package.json文件中main属性,如果.json解析错误,那么会抛出错误
   b. let M = X + (json main field)//M=X+main属性的值,这里注意了,如果main属性不存在或者main属性的值为空字符串或空白字符,那么是忽略c,d直接跳到2的
   c. LOAD_AS_FILE(M)//以LOAD_AS_FILE算法加载
   d. LOAD_INDEX(M)//以LOAD_AS_INDEX算法加载
2. LOAD_INDEX(X)//以LOAD_AS_INDEX算法加载
LOAD_NODE_MODULES(X, START)//LOAD_NODE_MODULES算法,这里是重点,这个算法的意思是递归向上级的node_modules子目录下查找模块或包
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS://递归向上级目录的子node_modules目录下查找,从嵌套最深的目录开始,向上递归
   a. LOAD_AS_FILE(DIR/X)//查找模块,如果没找到,跳到b
   b. LOAD_AS_DIRECTORY(DIR/X)//查找包,如果没找到,下一个循环
NODE_MODULES_PATHS(START)//NODE_MODULES_PATHS算法,这里也是重点
1. let PARTS = path split(START)//大概是这个意思PARTS=START.split('/'),START是路径
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
   a. if PARTS[I] = "node_modules" CONTINUE
   b. DIR = path join(PARTS[0 .. I] + "node_modules")//大概是这个意思DIR=PARTS[0]+...+PARTS[I]+"node_modules"
   c. DIRS = DIRS + DIR//大概是这个意思 DIRS.push(DIR),向数组末尾添加一个元素
   d. let I = I - 1
5. return DIRS
在每一层目录中,node会先以模块格式加载文件,再以包的格式加载文件。node在加载模块时,大概做了如下形式的封装:
function(exports,require,module,__filename,__dirname){
//模块内容在此
return module.exports;
}//其中module就是文件模块本身,exports是module的属性,

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多