1、resolve-cwd
当前工作目录解析
'use strict';
const resolveFrom = require('resolve-from');
module.exports = moduleId => resolveFrom(process.cwd(), moduleId);
module.exports.silent = moduleId => resolveFrom.silent(process.cwd(), moduleId);
2、resolve-from
'use strict';
const path = require('path');
const Module = require('module');
const fs = require('fs');
//fromDirectory:"D:\\FrameWork\\lerna", moduleId:"lerna\\cli.js",silent:true
const resolveFrom = (fromDirectory, moduleId, silent) => {
//判断路径是否是string
if (typeof fromDirectory !== 'string') {
throw new TypeError(`Expected \`fromDir\` to be of type \`string\`, got \`${typeof fromDirectory}\``);
}
//判断模块是否是string
if (typeof moduleId !== 'string') {
throw new TypeError(`Expected \`moduleId\` to be of type \`string\`, got \`${typeof moduleId}\``);
}
try {
//用于同步计算给定路径的规范路径名
//"D:\\FrameWork\\lerna"
fromDirectory = fs.realpathSync(fromDirectory);
} catch (error) {
if (error.code === 'ENOENT') {
fromDirectory = path.resolve(fromDirectory);
} else if (silent) {
return;
} else {
throw error;
}
}
//"D:\\FrameWork\\lerna\\noop.js"
const fromFile = path.join(fromDirectory, 'noop.js');
//在某个模块中给出的路径都是一个模块的相对路径,
//会先调用Module._resolveFilename这个方法来查找下这个文件的真实路径的全路径文件名
const resolveFileName = () => Module._resolveFilename(moduleId, {
id: fromFile,
filename: fromFile,
//Module._nodeModulePaths 解析出node_modules目录可能的路径
paths: Module._nodeModulePaths(fromDirectory)
});
if (silent) {
try {
//'D:\FrameWork\lerna\core\lerna\cli.js'
return resolveFileName();
} catch (error) {
return;
}
}
return resolveFileName();
};
module.exports = (fromDirectory, moduleId) => resolveFrom(fromDirectory, moduleId);
module.exports.silent = (fromDirectory, moduleId) => resolveFrom(fromDirectory, moduleId, true);
3、Module._resolveFilename
require解析并找到模块执行文件的流程-该部分需在复习
- Nodejs项目模块路径解析是通过require.resolve方式实现的。
- require.resolve就是通过Module._resolveFileName方法实现的
- Module._resolveFileName核心流程是:
- 判断该路径是否是内置模块
- 不是,则通过Module._resolveLookupPahts方法,生成node_modules可能存在的路径,如果传入的路径是’/test/lerna/cli.js’,在每一级路径下加上node_moduels的路径数组
- 通过Module._findPath查询模块的真实路径,
- Module._findPath核心流程是:
- 查询缓存(将request和paths通过\x00合并生成cacheKey)
- 遍历 Module._resolveLookupPahts方法生成的paths数组,将path与request组成文件路径basePath
- 如果basePath存在则调用fs.realPahtSync获取文件的真实路径
- 将文件真实路径缓存到Module._pathCache(key为cacheKey)(Module._pathCache就是一个map)
- fs.realPahtSync核心流程:
- 查询缓存(缓存的key为p。即Module._findPath中生成的路径)
- 从左往右遍历路径字符串,查询到/时,拆分路径,判断该路径是否为软链接,如果是软链接则查询真实链接,并生成新路径p,然后继续让后遍历,这里有一个细节:
- 遍历过程中生成的子路径base会缓存在knownHard和cache中,避免重复查询
- 遍历完成得到模块对应的真实路径,此时会将原始路径original作为key,真实路径作为value,保存到缓存中
- require.resolve.paths等价于Module._resolveLookupPaths,该方法获取所有node_modules可能存在的路径组成一个数组。
- require.resolve.paths实现原理是:
- 如果是/(根路径)直接返回[‘/node_modules’]
否则,将路径字符串从后往前遍历,查询到/时,拆分路径,在后面加上node_modules,并传入一个paths数组,直到查询不到/后返回paths数组 ```javascript // 进入mac电脑所在的逻辑: // from => /Users/rainbow/Documents/前端/脚手架开发/lerna源码/lernas //‘from’ is the __dirname of the module. Module._nodeModulePaths = function(from) { from = path.resolve(from); // Return early not only to avoid unnecessary work, but to avoid returning // an array of two items for a root: [ ‘//node_modules’, ‘/node_modules’ ] if (from === ‘/‘)
return ['/node_modules'];
const paths = [];
// 关键算法代码 for (let i = from.length - 1, p = 0, last = from.length; i >= 0; —i) {
const code = from.charCodeAt(i);
if (code === CHAR_FORWARD_SLASH) {
if (p !== nmLen)
paths.push(from.slice(0, last) + '/node_modules');
last = i;
p = 0;
} else if (p !== -1) {
if (nmChars[p] === code) {
++p;
} else {
p = -1;
}
}
}
// Append /node_modules to handle root paths. paths.push(‘/node_modules’);
return paths; };
```javascript
console.log(require.resolve("yargs"));
// /Users/rainbow/Documents/前端/脚手架开发/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/Documents/前端/node_modules',
'/Users/rainbow/Documents/node_modules',
'/Users/rainbow/node_modules',
'/Users/node_modules',
'/node_modules',
'/Users/rainbow/.node_modules',
'/Users/rainbow/.node_libraries',
'/usr/local/Cellar/node/14.3.0_1/lib/node'
]
作者:rainbowdiary
链接:https://juejin.cn/post/7040728919967793160
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
、
作者:rainbowdiary
学习来自:https://juejin.cn/post/7040728919967793160