循环依赖的产生
// main.js
import { funcB } from "./b.js";
funcB();
export var funcA = () => {
console.log("a");
};
第一行去加载b.js
// b.js
import { funcA } from "./main.js";
funcA();
export var funcB = () => {
console.log("b");
};
第一行又加载main.js,此时funcA并没有定义,直接执行就会报错
解决办法
比如业务代码main引用了A包, main,A需要分两个chunk,A包有个import B
如果打包的结果是 B打入了 chunkmain的内容,就会出现上面的这种情况
rollup生成图的时候,有这样的关系
B.importers -> A
那么是不是只要在split的时候,按照这个引用关系,把B打入到A的chunk之中就好了
const chunkGroups = {
'A-vendor': [
normalizePath(path.resolve('./src/a.js')),
],
}
manualChunks(id, { getModuleInfo }) {
for (const group of Object.keys(chunkGroups)) {
const deps = chunkGroups[group];
if (isDepInclude(id, deps, [], getModuleInfo)) {
return group; // chunk的名字,这里需要a.js和b.js都走到这步并且返回相同的名字
}
}
}
function isDepInclude (id, depPaths, importChain, getModuleInfo) {
id = normalizePath(id);
const key = `${id}-${depPaths.join('|')}`;
// 这步是防止自己引用自己,会造成死循环
if (importChain.includes(id)) {
cache.set(key, false);
return false;
}
if (cache.has(key)) {
return cache.get(key);
}
// 命中依赖列表 处理a.js会走到这步,b.js递归也会走到这步
if (depPaths.includes(id)) {
importChain.forEach(item => cache.set(`${item}-${depPaths.join('|')}`, true));
return true;
}
const moduleInfo = getModuleInfo(id);
if (!moduleInfo || !moduleInfo.importers) {
cache.set(key, false);
return false;
}
// 递归查找上层引用者
const isInclude = moduleInfo.importers.some(
importer => isDepInclude(importer, depPaths, importChain.concat(id), getModuleInfo)
);
// 设置缓存
cache.set(key, isInclude);
return isInclude;
};
处理b.js的时候,会去递归isDepInclude,然后命中了a.js,就会和a.js一起打入A-vendor
vite-plugin-chunk-split
用这插件就不用自己写分包代码了