Module._nodeModulePaths源码解析
获取当前目录下所有可能的
node_modules
路径
// 'node_modules' character codes reversed
const nmChars = [115, 101, 108, 117, 100, 111, 109, 95, 101, 100, 111, 110];
const nmLen = nmChars.length;
Module._nodeModulePaths = function (from) {
// Guarantee that 'from' is absolute.
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"];
// note: this approach *only* works when the path is guaranteed
// to be absolute. Doing a fully-edge-case-correct path.split
// that works on both Windows and Posix is non-trivial.
const paths = [];
for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
const code = StringPrototypeCharCodeAt(from, i);
if (code === CHAR_FORWARD_SLASH) {
if (p !== nmLen)
ArrayPrototypePush(
paths,
StringPrototypeSlice(from, 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.
ArrayPrototypePush(paths, "/node_modules");
return paths;
};
执行流程
1. 解析路径为绝对路径
from = path.resolve(from);
2. 根目录直接返回 /node_modules
if (from === "/") return ["/node_modules"];
如果当前传入目录为根路径的话,则直接返回 ['/node_modules'],否则执行遍历动作
3. 遍历添加 path
遍历各级目录,顺着目录依次向上查找,在每一级目录后面都添加 /node_modules
然后放入 paths 中进 行返回
const paths = [];
// !!!p 用来判断当前字符串是否和 node_modules 相等
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)
ArrayPrototypePush(
paths,
StringPrototypeSlice(from, 0, last) + "/node_modules"
); // 推入带有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.
ArrayPrototypePush(paths, "/node_modules");
return paths;