nodejs 相对路径,node 路径
本文带你了解Node.js中的模块路径解析,并介绍Node中模块路径解析的方法。希望对你有帮助!
node.js速度课程简介:进入学习
require案例
当前有一个项目。当前项目路径/Users/rainbow/Documents/front-end/scaffold development/rainbow-test项目bin目录下有一堆文件。
/bin/index . js console . log(require . resolve( . )));
///Users/rainbow/Documents/前端/脚手架开发/rainbow-test/bin/index.js输出bin/index.js的绝对路径
console . log(require . resolve . paths( . )));
//[/Users/rainbow/Documents/front-end/scaffold development/rainbow-test/bin ]输出文件可能所在路径的Array console . log(require . resolve( yargs );
///Users/rainbow/Documents/front-end/scaffold development/rainbow-test/node _ modules/yargs/index . cjs
console . log(require . resolve . paths( yargs ));
/*
[
/Users/rainbow/Documents/前端/脚手架开发/rainbow-test/bin/node_modules ,
/Users/rainbow/Documents/前端/脚手架开发/rainbow-test/node_modules ,
/用户/彩虹/文档/前端/脚手架开发/节点_模块,
/用户/彩虹/文档/前端/节点_模块,
/Users/rainbow/Documents/node _ modules ,
/Users/rainbow/node_modules ,
/用户/节点模块,
/node_modules ,
/用户/彩虹/。节点模块,
/用户/彩虹/。节点_库,
/usr/local/Cellar/node/14 . 3 . 0 _ 1/lib/node
]
*/
require解析并找到模块执行文件的流程
1.Nodejs项目模块的路径解析通过require.resolve实现
Require.resolve是模块实现的模块。_resolveFileName方法。_ ResolveFilename的核心过程是判断路径是否是内置模块,然后由模块生成node_modules的可能路径。_resolveLookupPahts方法。如果传入路径为/test/lerna/cli.js ,则在每一级路径下添加node _ moduels的路径数组,通过module查询模块的真实路径。_findPath。2.模块的核心流程。_findPath是:
查询缓存(通过\x00组合请求和路径来生成cacheKey)遍历模块生成的路径数组。_resolveLookupPahts方法,将路径和请求转换为文件路径basePath。如果basePath存在,调用fs.realPahtSync获取文件的真实路径,并将文件的真实路径缓存到模块。_pathCache(key是cacheKey)(模块。_pathCache是地图)。3.fs.realPahtSync核心进程:
查询(缓存的键是p .也就是模块中生成的路径。_findPath)从左到右遍历路径字符串。找到/时,拆分路径以确定该路径是否为软链接。如果是软链接,查询真实链接,生成新的路径P,然后继续遍历。这里有个细节:遍历过程中生成的子路径基会缓存在knownHard和cache中。避免重复查询遍历来获取模块对应的真实路径。此时,原始路径将被用作键,真实路径将被用作值,这些值将被保存在缓存中。4.require.resolve.paths相当于模块。_resolveLookupPaths。该方法获取node_modules的所有可能路径,形成一个数组。
5.require.resolve.paths的实现原理是:
如果是/(根路径)直接返回[/node_modules],否则,从后向前遍历路径字符串,当找到/时,拆分路径,在后面加上node_modules,传入一个paths数组,直到没有找到/为止,然后当我们使用require(yargs )时,返回paths数组
require使用到内置模块的方法
。
require方法
实际上,模块。_load方法module . prototype . require=function(id){//id= yargs
validateString(id, id );
if (id===) {
throw new ERR _ INVALID _ ARG _ VALUE( ID ,id,必须是非空字符串);
}
要求深度;
尝试{
返回模块。_load(id,this,/* isMain */false);
}最后{
要求深度-;
}
};//参数
id=yargs
这={
路径:模块。_nodeModulePaths(process.cwd())
}Module._nodeModulePaths方法
//输入mac电脑所在的逻辑:
//from=/users/rainbow/documents/front-end/scaffold development/ler na source/ler nas// from 是模块的_ _ dirname。
模块。_ nodeModulePaths=function(from){
from=path . resolve(from);
//尽早返回不仅是为了避免不必要的工作,也是为了避免返回
//根的两个项目的数组:[ //node_modules ,/node_modules ]
if (from===/)
return[/node _ modules ];
常量路径=[];
//关键算法代码
对于(设i=from.length - 1,p=0,last=from . length I=0;- i) {
常量代码=from。charcodeat(I);
if (code===CHAR_FORWARD_SLASH) {
如果(p!==nmLen)
paths.push(from.slice(0,last)/node _ modules );
last=I;
p=0;
} else if (p!==-1) {
if (nmChars[p]===code) {
p;
}否则{
p=-1;
}
}
}
//追加/节点_模块来处理根路径。
路径。push(/node _ modules );
返回路径;
};为循环的核心算法解析:
Module._load方法
模块. load(id,this,/* isMain */false)
核心实现代码是:常量文件名=模块. resolveFilename(request,parent,is main);
require.resolve
节点。射流研究…项目模块路径解析是通过要求。解决方式实现的。
要求。解决就是通过模块.解决文件名方法实现的,//node.js内置模块需要的源代码
函数解析(请求,选项){
验证字符串(请求,‘请求’);
返回模块. resolveFilename(request,mod,false,options);//核心实现
}
require.resolve=resolve
函数路径(请求){
验证字符串(请求,‘请求’);
返回模块. resolveLookupPaths(request,mod);//核心代码
}
resolve.paths=pathsModule._resolveFileName核心流程
判断该路径是否是内置模块不是,则通过模块resolveLookupPahts方法,将小路和环境中的路径结合起来通过模块. find path _ find path查询模块的真实路径返回模块. resolveFilename(request,parent,is main);
模块. resolve filename=function(request,parent,isMain,options) {
if(原生模块。canberequiredbyusers(request)){//是否为内置模块
退货请求;
}
让路径;
//让小路和环境变量中的小路结合
路径=模块. resolveLookupPaths(请求,父级);//核心代码
if (parent parent.filename) {
//读取文件名对应的package.json文件,看是否有出口字段,当前文件名=假
const filename=try self(parent。文件名,请求);
如果(文件名){ //false
const cacheKey=request \x00
(paths.length===1?路径[0]:路径。加入( \ x00 );
模块. path cache[cache key]=filename;
返回文件名;
}
}
//关键代码,找到本地执行文件//首先查找文件名,因为那是缓存键。
常数文件名=模块. findPath(request,paths,isMain,false);
如果(文件名)返回文件名;
//.
};Module._resolveLookupPahts方法
生成要查找模块的所有路径上可能存在节点_模块的路径数组require.resolve.paths(yargs )核心实现方法生成
[
/用户/彩虹/文档/前端/脚手架开发/rainbow-test/bin/node_modules ,
/用户/彩虹/文档/前端/脚手架开发/rainbow-test/node_modules ,
/用户/彩虹/文档/前端/脚手架开发/node_modules ,
/用户/彩虹/文档/前端/node_modules ,
/Users/rainbow/Documents/node _ modules ,
/Users/rainbow/node_modules ,
/用户/节点模块,
/node_modules ,
/用户/彩虹/。节点模块,
/用户/彩虹/。节点_库,
/usr/local/Cellar/node/14。3 . 0 _ 1/库/节点
]
模块resolveLookupPaths=function(request,parent) {
if(原生模块。canberequiredbyusers(请求)){
调试(在[]中查找%j,请求);
返回空
}
//检查节点模块路径。
if (request.charAt(0)!==.
(请求长度一
request.charAt(1)!==.
request.charAt(1)!==/
(!isWindows request.charAt(1)!==\))){
设路径=模块路径
如果(家长!=空父级。父路径。路径。长度){
路径=父路径。路径。concat(路径);
}
调试(在%j中查找“%j”,请求,路径);
返回路径。长度0?路径:空;
}
//在REPL,家长.文件名为空。
如果(!父!parent.id !parent.filename) {
//Make require( ./path/to/foo’)工作-通常采用路径
//来自实路径(_ _文件名),但在取代没有文件名
const mainPaths=[ . ];
调试(在%j中查找“%j”,请求,主路径);
返回主路径;
}
debug( RELATIVE:requested:% s来自父级。id % s ,请求,父级。id);
const父目录=[路径。目录名(父级。文件名)];
调试(寻找“%j”,父目录);
返回父目录
};Module._findPath核心流程
查询缓存(将请求和小路通过\x00合并生成cacheKey)(\x00是空格的16进制)遍历模块resolveLookupPahts方法生成的小路数组,将小路与请求组成文件路径基本路径如果基本路径存在则调用fs.realPahtSync获取文件的真实路径
fs.realPahtSync
更多结节相关知识,请访问:节点射流研究…教程!以上就是一文聊聊节点。射流研究…中的模块路径解析的详细内容,更多请关注我们其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。