通用插件设计 - 使用 SWC & ESBuild 加速你的项目构建

Webpack 构建提速插件是一整套提升前端项目构建速度的插件,能提供一个通用的解决方案,无需针对项目做特别的配置。

一、背景

背景其实就是我们目前的前端构建速度还是太慢,经常会达到 6、7min 以上,这对于开发效率来说是一个很大的影响。

二、使用方式

总共五个插件体系,可单独使用也可以集合使用:

  • 支持 swc 与 esbuild 构建
  • 支持 DLL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module.exports = {
entry: '...',
output: {
// ...
},
module: {
// ...
},
plugins: [
// Currently the plugin supports esbuild and swc builds, so please choose one of them, there will be a warning if both are set to true
new FEBuilderImprovePlugin({
// swc: true,
// esbuild: true,
// dll: true,
// closeSourceMap: true,
// closeESLint: true
}),
],
};

三、插件设计

1. febuilder-improve-plugin

  • 插件执行逻辑设计,根据用户插件参数配置
    • 开启 esbuild/swc 构建
      • 替换 babel-loader 和 TerserPlugin 这两个耗时久的插件
      • 参数转换,平滑适配
    • 开启 dll 构建优化

febuilder-improve-plugin 的构建过程,中间在初始化参数之后会在 webpack 的 environment 钩子处将 babel-loader 和 TerserPlugin 自动替换掉,同时针对 babel-loader 到 swc 编译做了一些更平滑的参数适配,尽量保证用户不需要做一些额外的处理,能达到平滑替换。

2. swc-core

  • 为什么要整这样一个包?
    • 官方提供的包体积特别大(经排查是没有区分不同平台的版本),导致依赖安装速度特别慢(37s)
  • 优化效果,依赖安装速度 4s
    • 从 37s -> 4s,大致有九倍速度提升
    • 从 100M -> 8M,依赖安装体积仅占官方的不到 10%

swc-core 是 swc 最核心的提供编译能力的包,那么我们封装的 swc-core 和官方的有什么区别?或者说为什么要再封装一个?

我们可以看一下左边的这个图,swc 是 RUST 来构建的,不同平台编译会有不同的包来处理,所以会把所有的包都下载下来,然后再根据当前平台和操作系统仅仅保留一个用于编译构建的版本,这就导致一个问题。一个包大概 6-8M 左右,13个包大概 100M,如果说为了提升build的构建速度,而导致依赖安装耗费了更多的时间,显然得不偿失。因此我们基于这种情况做了一些优化。

  • 优化手段流程设计
    • 利用 npm script 的 post install 钩子
    • 手动获取当前平台信息,安装指定版本的文件

如右图所示,我们会放弃默认安装所有文件,而是利用 npm script 的 postinstall, 会在 swc-core 安装后默认执行,然后这个时候我们会手动去获取平台信息,然后在指定位置执行 npm install脚本,安装指定版本的文件,这样就可以保证只下载一个平台的包。

优化结果 100M -> 8M ,然后可以看一下整体的安装耗时,这个耗时都是在 cache clean 之后对比的。优化结果还是比较明显的,不至于说引入我们的包导致依赖安装有更多的耗时。

3. febuilder-dll-plugin

  • 为什么要整这样一个包?
    • 希望从 DLL 动态链接这个常规角度,提供一个更为方便的构建速度优化方式

流程设计

  1. 利用 environment 钩子注入插件
  2. 监听 Run & WatchRun 插入构建逻辑
  3. 检测 package.json 依赖变化
  4. contenthash 文件命名,保证浏览器缓存命中

优化提升:配置流程大大简化

  • 左侧常规配置,需要启动两次 webapck 构建
  • 右侧使用 @shopee/febuilder-dll-plugin 插件,只用一次构建,自动分析

四、总结

插件的收益还是很明显的,经过测试基本有 67% 的速度提升,这个速度提升对于我们的项目来说还是很有意义的,能够提升开发效率,减少等待时间。