umi项目构建加速:多进程 / externals / cache

好长时间了,我的umi项目打包速度好慢。不管是平时启动开发模式,还是生产模式打包。测了一下,生产模式每次打包大概要2分钟左右。下决心优化一下。

另外,umi其实在打包加速方面已经开箱即用地帮我们做了很多优化,所以我们即使什么都不做,目前看到的打包速度,已经是umi上了种种优化手段之后的结果了。

这里主要记录一下我尝试的一些主流的、umi默认没有使用的加速手段。

❌多进程打包 ------ happypack / thread-loader

webpack对文件的解析和处理默认是单线程的,文件数量很多时,解析和处理文件的时间就会越来越长,打包的速度就会变慢。

happypackthread-loader都是通过多进程打包来提升webpack打包速度。happypack目前已经不再维护了,所以更推荐使用thread-loader

在umi中更改处理文件的loader需要使用webpack-chain的api。配置thread-loader需要把它添加到module.rule.use数组的第一个。

在此贴一下umi配置thread-loader的代码:

javascript 复制代码
//config/config.ts 
chainWebpack(config, { webpack }) {
  config.module
    .rule("js")
    .use("thread-loader")
    .loader("thread-loader")
    .before("babel-loader");
    
  config.module
    .rule("ts-in-node_modules")
    .use("thread-loader")
    .loader("thread-loader")
    .before("babel-loader");
    
  config.module
    .rule("js-in-node_modules")
    .use("thread-loader")
    .loader("thread-loader")
    .before("babel-loader");
}

配置完成后可以通过config.toString()查看修改后的完整配置。

但是在配置thread-loader之后,发现对打包速度并没有提升,基本上没变化。查了一下,发现它对加速的loader是有要求的,不允许使用自定义loader的api。

umi中使用的loader是umi封装过的,而不是原装的babel-loader等。这是umi中的部分loader配置:

所以thread-loader配置之后也没有起到加速效果,多进程打包在umi这里没有走通。

❌externals

我们项目中总是有一些很少更新的、体积又不小的第三方库,比如react / react-dom / lodash等。这些库很少发生更改,但是我们每次打包都要把它们重新构建一遍。这就造成了打包时间的浪费。为了节省这部分时间,我们就要用到webpack的externals

externals配置用于将一些第三方库排除出打包过程,不出现在最终的打包结果中。再通过其他方式引入它们,比如<script>标签引入。

举个栗子:我们可以像这样配置externals,它的值是一个对象,key是第三方库的名字,value是通过<script>引入的全局变量的名字:

javascript 复制代码
{
  //...other webpack config
  externals: { 
    react: "React", 
    lodash: "_", 
    "react-dom": "ReactDOM" 
  },
};

这样,我们就可以把react / react-dom / lodash排除出打包过程,减少webpack需要打包的模块数量,以提升webpack的打包速度。

之后,不要忘记在项目的html中手动引入这些依赖包:

html 复制代码
<script src="https://unpkg.com/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.14.0/umd/react-dom.production.min.js"></script> 
<script src="https://raw.githubusercontent.com/lodash/lodash/4.17.21-npm/lodash.min.js"></script>

至此,externals的配置就OK了。但是实际上,我测了一下,对项目的打包速度提升很有限。可能是我的项目原本的体积比较大。

另外,还有一个问题,就是externals虽然将这些第三方库排除出了打包过程,参与打包过程的模块是少了。但并不意味着我们需要加载的文件体积减少了。通过<script>引入的文件,依然需要加载。而且通过<script>引入的这些文件,不参与打包,webpack是没有办法对其进行tree shaking的。所以对于支持tree shaking的库要注意,通过<script>引入的文件体积是不是比原来打包的产物体积大很多。

比如antd,支持tree shaking,官方文档里也提到,虽然支持通过<script>标签引入,但不建议这么做。

✔ cache

webpack 5提供了新的特性:cache。开启cache之后,webpack会将首次打包的结果持久化到本地文件系统中。在下一次构建时,对于未更新的文件,跳过解析、链接、编译等一系列非常消耗性能的操作,直接复用上一次打包的结果。通过这种方式,大幅度提升打包速度。

在umi项目中,需要手动开启cache。我的项目是umi v3。通过如下选项开启:

javascript 复制代码
{ 
  //...other umi config 
  webpack5: {} 
}

开启之后,打包快了很多很多。开启之前,每次build大概105s左右;开启之后,大概12s左右。

umi v3默认使用webpack 4打包。如果不想开启webpack 5,不用webpack 5的cache特性的话,可以考虑通过cache-loader / DLL plugin等在webpack 4中实现缓存。

相关推荐
不能只会打代码18 分钟前
六十天前端强化训练之第一天HTML5语义化标签深度解析与博客搭建实战
前端·html·html5
OpenTiny社区35 分钟前
Node.js技术原理分析系列——Node.js的perf_hooks模块作用和用法
前端·node.js
菲力蒲LY39 分钟前
输入搜索、分组展示选项、下拉选取,全局跳转页,el-select 实现 —— 后端数据处理代码,抛砖引玉展思路
java·前端·mybatis
MickeyCV2 小时前
Nginx学习笔记:常用命令&端口占用报错解决&Nginx核心配置文件解读
前端·nginx
祈澈菇凉2 小时前
webpack和grunt以及gulp有什么不同?
前端·webpack·gulp
zy0101012 小时前
HTML列表,表格和表单
前端·html
初辰ge2 小时前
【p-camera-h5】 一款开箱即用的H5相机插件,支持拍照、录像、动态水印与样式高度定制化。
前端·相机
HugeYLH3 小时前
解决npm问题:错误的代理设置
前端·npm·node.js
六个点3 小时前
DNS与获取页面白屏时间
前端·面试·dns
道不尽世间的沧桑3 小时前
第9篇:插槽(Slots)的使用
前端·javascript·vue.js