前言
- 上一次写的构建优化记录已经把单一webpack整的都没啥能优化的了。但是打包速度仍然不理想。于是我制作了create-activity-script脚手架,但是这个脚手架只能用在新项目,老项目由于目录问题非monorepo问题无法使用。所以我又做了一个更定制化的改动。
过程
-
我们这个项目总入口超过200,也就是说每次打包要打包200多个应用,而且这些东西都集中在一个webpack配置和一个项目中,所以时间非常长。
-
我使用脚本来控制webpack打包规则,多次执行webpack,生成缓存进行打包,另外设定规则,在满足规则时,打包对应的入口。
-
多页应用打包的东西有很多重复的,所以划分需要有点讲究,我们老项目是以文件夹划分(每个文件夹下还是个多入口项目),如果该文件夹下某一个入口发生改动,该文件夹下所有入口重新打包(因为一个文件夹下的耦合性相当高,这样避免打包出太多重复的)。
-
将打包完成的文件作为缓存,通过脚本生成最后的打包项目即可。
-
作为提升打包速度的代价,第一次打包时间会相当长(但不用担心内存过大问题,以前打包需要把node的内存上线调到10g才能打包出来),可以在本地打包完再上传。另外,需要提交缓存文件,我们有3个环境,每个环境需要提交约1g的缓存文件。但在工作流中使用时就不需要每次进行打包了。
-
后来,觉得这个缓存实在太大,于是进行分析每个页面,发现入口引用不规范等问题,我们把活动页和主页进行分开打包,所以每个活动页正常来说是很少的,但是该项目中居然有人在主页入口处写了个 commonjs语法导致了每次打包活动页都会把主页上路由全部打包一遍。加上另外还有2处地方引用的方法间接引入了vue-router,从而导致又把主页路由打包进去了。
-
经过分析后的缓存就相当小且没啥重复的。
遇到的坑
cross-spawn
- 我一直以为cross-spawn能很好的解决问题,事实上不能,cross-spwan在本地运行的好好的,在工作流的linux机子上就运行不起来,换成原生的child_process就可以。
筛选条件
- 前面说要满足某种筛选条件进行打包,一开始是以位看file的status时间,其实不行,谁拉下来时间都是最新,所以需要看git时间,那么如何根据git时间?这里免费分享下:
async function findGit(f, v) {
return new Promise(resolve => {
const command = `git`;
const args = ["log", "--pretty=format:%at", "-1", `${f}`];
const child = spawn(command, args);
let res = {
name: v,
time: null
};
child.stdout.on("data", data => {
res["time"] = data.toString();
});
child.on("close", () => {
setTimeout(() => {
resolve(res);
});
});
});
}
子进程node环境
- 同样是本地运行没问题,拉去部署机子上就挂,在尝试了各种命令后发现这样使用:
async function buildFatAction(name) {
return new Promise(resolve => {
const command = `cross-env`;
const args = [
`VUE_APP_BUILD_MODE=activity BUILD_PROJECT=${name} vue-cli-service`,
"build",
`--mode ${mode}`
];
const child = spawn(command, args, {
stdio: "inherit",
env: process.env,
shell: true
});
child.on("close", resolve);
});
}