Open
Description
最小复现仓库地址
webpack5-cache-debug
webpack版本如下
"devDependencies": {
"webpack": "^5.10.3",
"webpack-cli": "^4.2.0"
},
webpack配置文件如下
webpack.config.js
module.exports = {
cache: {
type: 'filesystem' //写入缓存到硬盘
},
snapshot: {
managedPaths: [path.resolve(__dirname, 'node_modules')],//配置包管理器管理的路径
}
}
经过认真排查确定问题出在这里
https://github.com/webpack/webpack/blob/911ec1aa67011e25aa1449610f5b0b557edd5459/lib/FileSystemInfo.js#L1571
-
就是wepback5约定包名必须以@开头。如果不是以@开头的话就直接返回null了,导致无法webpack5无法获取管理资源,导致会计算包下所有的文件和文件夹的hash值和时间戳,导致超时假死
-
正常的包名是
C:/node_modules/@babel_helper-module-import
-
cnpm安装的包名为
C:/node_modules/_@babel_helper-module-import
测试代码如下
const getManagedItem = (managedPath, path) => {
debugger
let i = managedPath.length;
let slashes = 1;
let startingPosition = true;
loop: while (i < path.length) {
switch (path.charCodeAt(i)) {
case 47: // slash
case 92: // backslash
if (--slashes === 0) break loop;
startingPosition = true;
break;
case 46: // .
// hidden files are disallowed as managed items
// it's probably .yarn-integrity or .cache
if (startingPosition) return null;
break;
case 64: // @
+ if (!startingPosition) return null;
slashes++;
break;
default:
startingPosition = false;
break;
}
i++;
}
if (i === path.length) slashes--;
// return null when path is incomplete
if (slashes !== 0) return null;
// if (path.slice(i + 1, i + 13) === "node_modules")
if (
path.length >= i + 13 &&
path.charCodeAt(i + 1) === 110 &&
path.charCodeAt(i + 2) === 111 &&
path.charCodeAt(i + 3) === 100 &&
path.charCodeAt(i + 4) === 101 &&
path.charCodeAt(i + 5) === 95 &&
path.charCodeAt(i + 6) === 109 &&
path.charCodeAt(i + 7) === 111 &&
path.charCodeAt(i + 8) === 100 &&
path.charCodeAt(i + 9) === 117 &&
path.charCodeAt(i + 10) === 108 &&
path.charCodeAt(i + 11) === 101 &&
path.charCodeAt(i + 12) === 115
) {
// if this is the end of the path
if (path.length === i + 13) {
// return the node_modules directory
// it's special
return path;
}
const c = path.charCodeAt(i + 13);
// if next symbol is slash or backslash
if (c === 47 || c === 92) {
// Managed subpath
return getManagedItem(path.slice(0, i + 14), path);
}
}
return path.slice(0, i);
};
console.log(getManagedItem('C:/node_modules/','C:/node_modules/_@babel_helper-module-import'));
打印null
Activity
[-]webpack5和持久化缓存和cnpm的安装包名之间有冲突,导致webpack5假死,无法生成缓存文件[/-][+]webpack5的持久化缓存和cnpm的安装包名之间有冲突,导致webpack5假死,无法生成缓存文件[/+]fengmk2 commentedon Dec 19, 2020
我今天会跟进看看。
fengmk2 commentedon Dec 19, 2020
我简单看了一下,主要是 webpack 读取了绝对路径,这个比较难搞。cnpm 使用了软连接来提速。可能还需要看看 snapshot 的 managedPaths 配置。
zhangrenyang commentedon Dec 19, 2020
@fengmk2 是的,比较棘手。
主要原因在于webpack写死了这个规则,而这个规则是符合标准的,并非webpack的BUG或者问题,所以webpack几乎不可能修改它的规则。
而cnpm这种模式也不好改,要去迎合webpack的规则改动也会比较大。
关于snapshot的配置我都仔细研究过了,个人认为跟
managedPaths
配置关系不大了,主要问题就在这个读取规则上,如何兼容。lceric commentedon Jun 23, 2021
可以试着本地patch一下,调整一下这个规则