闻心阁

一蓑烟雨看苍生,半壶浊酒笑红尘

使用esbuild-loader加速前端工程打包速度(亲测提速50%)

2022-06-03 约 1 分钟读完 搬砖秘籍

在五月底项目上线的时候突然被卡住了,部署不了,因为云效的构建总时长有限制。为了给项目节省资源,想着从前端工程的角度做一些优化,主要使用的工具是esbuild-loader

项目背景

前端项目使用的工程化设施有点久远,原始项目使用的是 Webpack3 + Ant-Design 3 + Mobx,后来为了前端UI规范标准化,又在引入了新的G3组件库(基于Ant-Design 4)。

大约梳理了一下构建脚本需要处理的工作如下:

  1. 基础loader处理工作(如js、less、图片)
  2. dll公共包处理
  3. Ant-Design 3 与 ant-design 4 共存
  4. 注入环境变量
  5. ES-Lint检查
  6. 其他项目运行相关

所以项目的打包构建脚本中有不少历史包袱,在改造的同时需保证原项目所有功能正常运行。

找到的解决方案

在网上找了一圈解决方案,大约整理如下:

  1. 升级 Webpack
  2. 使用 Vite 重写
  3. 使用 ESBuild 重写
  4. 使用 esbuild-loader “无痛”改造

最后选了方案4.

对比了一下,其实开始想使用方案一,也就是升级webpack版本,但时间有点紧,需要把之前所以的配置重写,在 webpack 配置这块我也不是特别有经验,于是做为备选。方案2和3也是一样,需要重新搭建脚手架,可能需要排在后期来尝试。

接入方法

esbuild-loader 这个插件顾名思义,就是把esbuild的能力包装成Webpack的loader来实现js、ts、css等资源的打包编译。

安装 esbuild-loader

// npm
npm i -D esbuild-loader

//yarn
yarn add -D esbuild-loader 

配置loader

esbuilder-loader支持绝大部分前端常用的文件类型打包,本项目中主要是前端js页面文件打包比较耗时,所以只替换了js文件相关的打包部分。

rules: [
  {
    test: /\.(js|jsx)$/,
    // use: 'happypack/loader?id=jsx',
    loader: 'esbuild-loader?id=jsx',
    options: {
      loader: 'tsx',
      target: 'es2015',
      // 定义你需要的环境变量
      define: {
        ENV: JSON.stringify(process.env.ENV || 'dev'),
      }
    },
    include: path.join(__dirname, 'src'),
    exclude: /(node_modules)/
  },
  // other rules
]

这里为啥.jsx使用的是tsx的loader?这个后面在问题里再细说。

PS:真实项目中改造其实更加复杂,这里只是一个简单的demo,由于相关问题都是具体项目相关,这里不赘述了。

效果实测试

使用原来的happypack的打包时间

优化后的打包时间:

从42s变成21s,速度提升50%。

遇到的问题

改造过程中遇到了不少问题,这里也统一记录一下。

环境变量丢失

原来使用DefinePlugin完成的操作。

解决方案要手动转移到esbuild-loaderdefine字段。

mobx失效

因为mobx使用的是@装饰器,但esbuild-loader中的jsx不支持装饰器语法。

解决方案是使用tsx的loader。

less样式丢失

因为原来的ant-design 3的样式是通过babel-import-plugin实现的,esbuild-loader目前不支持。

解决方案全局引入ant-design样式

不支持原生esbuild插件

esbuild-loader使用的是esbuildtrasform API,而它的插件是使用build方法时注入的。这个的详细内容可以参考:

Possibility of using esbuild plugins · Discussion #119 · privatenumber/esbuild-loader

方案总结

使用esbuild-loader可以快速将老项目中的loader替换,借用esbuild的能力实现前端工程的快速打包构建。

优点

  1. 改造小,几乎是开着火车换轮子式的外科手术操作,对项目影响最小,时间就是生命。
  2. 速度提升明显,尤其是对于页面繁多的老工程项目。

缺点

  1. 没那么快(我个人猜测完全改造成vite会更快)
  2. 功能还比较简陋,不支持原生插件,还是要踩不少坑

后续规划

  1. 如果时间允许,想尝试直接转 vite。
  2. 如果时间紧,那就尝试升级下webpack版本(大概率是这条路子)

欢迎有相关经验的大佬留言提出更好的方案。