基于Rspack实现大仓应用构建提效实践|得物技术

Rspack构建优化实战

一、实践背景

随着项目的逐步迭代,代码量和依赖的逐渐增长,应用的构建速度逐步进入缓慢期。以目前所在团队的业务应用来看(使用webpack构建),应用整体构建耗时已经普遍偏高,影响日常开发测试的使用效率,其中编译耗时大约占50%。

实际上随着近些年前端的技术发展以及业务对前端交互体验的要求提高,前端整个代码量复杂度和代码量增长飞快。随着这一趋势的变化,服务于前端工程构建方案多年的webpack,在构建效率上已经逐渐成为瓶颈。因此业界也存在不少优化思路和方案,主要分两个方向:

  • 基于原有Node.js语言实现,通过缓存等方案来提升构建效率,主要是缓存、预构建的方式来减少编译。此类方案多数存在条件限制,比如缓存方案前提是第一次先生成缓存来提升二次构建效率,对于发布平台等需要冷启场景无法生效。
  • 另外一类是采用Golang、Rust等语言重新实现耗时较为复杂的编译过程,从语言层面实现编译过程的性能提升。比较有代表的有,基于Golang实现的esbuild、基于Rust实现的SWC,都在对应的场景得到不少的性能提升。

二、业界方案

既然是业界的普遍性问题,那么外界也肯定会存在不少优化案例可以借鉴或者复用。由于Node.js的优化方案通常都会存在各种场景限制,这里我们主要从另外一个思路去寻找方案。经过调研目前业界的主要方案有Rspack、Vite、Turbopack、swcpack相对比较有代表性(可能还有其他方案,由于笔者时间精力有限未能了解到)。几个方案主要的情况如下(笔者个人主观分析,仅供参考):

01.jpg

三、技术选型

先看当前大仓前端应用主要技术体系:整体技术栈主要是React为主,未来Vue还会逐步迁移React;框架层面UmiJS@4大概占60%、UmiJS@v3大概占20%、剩余为其他Vue或者C端的多页应用。整体技术体系主要是UmiJS为主,配套主要是webpack的构建方案,部分Vue项目有使用Vite。

在这样的现实情况下,我们面对的主要是React+UmiJS+webpack的应用。基于应用广泛性考虑,只要解决这部分应用就可以达到80%的应用提速覆盖。为此,我们选择了基于Rspack来实现构建方案的性能提升,主要考虑有以下几点:

  • 高性能:基于Rust实现核心能力,全量编译+增量编译(HMR)的实现方式,官方宣称实际落地有5~10倍的提升,随着未来逐步优化完善还有提升空间,且生产和开发阶段除缓存之外,基本可以获得一致性的性能收益。
  • 低成本:Rspack大量兼容webpack生态,大量配置和插件可以直接或者调整一下配置即可复用,仅需对一些特殊的插件自研定制开发即可。以下是对项目主要使用到的webpack能力进行了梳理,并对其在Rspack中的情况情况也进行了对照。

02.jpg

综合情况来看:虽然性能Rspack未必是最高的,但其兼容webpack生态带来的低成本迁移,是其他的方案基本上无法做到的。对此,选择了基于Rspack来作为基础的底层能力。得益于此,我们最终实现了业务代码零改动即可实现构建方案迁移(仅微调构建配置),并获得云构建2倍+编译性能的提升。

四、方案设计思路

由于大仓目前大量的应用为UmiJS@4体系,作为我们主要服务的目标对象,本文也是主要先针对解决UmiJS@4版本的应用方案。

方案难点

  • UmiJS仅支持webpack和Vite两种构建模式,如何扩展Rspack构建?
  • 业务应用中有大量使用UmiJS插件、Babel插件来实现一些特殊能力,如何支持此类插件的能力?
  • 如何尽可能降低业务应用接入成本,进而达成方案快速应用到各个业务应用中?

通过扩展插件命令实现Rspack构建

UmiJS默认构建能力是封装在@umi/max内部,通过max dev/build来调用内置配套的本地/生产构建。在UmiJS官方上并未提供编译能力的完全自定义扩展能力,仅支持Vite/webpack的选择以及提供了一些修改构建配置的方法。

通过查看UmiJS项目的源码,发现其内部的构建实现全部集中在dev/build这两个扩展命令中。源代码在preset-umi/src/commands/目录下的dev/dev.ts和build.ts 两个文件,分别对应dev和build命令。而实际上的构建逻辑,实现上主要是在 @umijs/bundler-vite 和 @umijs/bundler-webpack两个包中。其内部执行的主要逻辑如下(这里以dev模式为例,build模式基本上类似,就是少了文件监听编译和express相关逻辑):

03.jpg

那么我们只需要在新的命令中实现相关的逻辑,即可通过扩展命令的方式来扩展Rspack构建能力。另外,使用该方法实现,还能沿用UmiJS原本的代码生成等原本的插件,进而可以避免需要大量重新实现UmiJS插件的能力,并降低重写带来的逻辑不一致风险。

官方平替插件+少部分自研扩展支持原有插件能力

前面的插件扩展模式已经能保证原有大量的UmiJS能力是可以直接沿用的,比如生成路由、添加tailwind.css等UmiJS内置能力都可直接沿用。另外项目主要依赖扩展的插件,除了少部分修改构建能力的插件之外,基本上都可以直接使用或者少量适配即可。不兼容的几个插件主要是因为:功能是通过修改的webpack配置来调整构建能力,需要通过使用对应的Rspack构建能力来进行兼容。

另外除了UmiJS的插件之外,还有构建依赖的Babel插件部分,当然部分Babel插件也是通过UmiJS插件引入使用的。对此,也对主要的Babel插件的情况进行了梳理,其主要的情况如下表:

04.jpg

所以整体上还是以沿用webpack原有扩展加Rspack官方能力替换为主,只需要针对少部分未支持的Babel插件进行扩展即可实现。

<
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值