我们的前端项目是从Vite 2.x时代开始的,一路升级到4.0。功能越加越多,代码也越来越乱。构建配置文件写了几百行,插件堆了十几个,构建速度越来越慢。

终于有一天,构建一次要等五分钟,改个配置要翻半天文档,我们决定彻底重构一次。这篇文章记录整个过程。

重构前的状况

先说重构前有多乱。vite.config.js里堆了各种插件,有的已经不用了但没删,有的配置重复了好几遍。环境变量散落在各个地方,开发、测试、生产的配置混在一起,改一个环境的设置要找半天。

代码结构也有问题。组件目录里混着工具函数和常量,hooks写在组件文件里,样式有的用CSS Modules有的用Tailwind还有的用内联样式。新人接手看代码,完全摸不着头脑。

构建性能更是灾难。冷启动要等一分多钟,热更新经常失效,改个样式要等好几秒才能看到效果。生产构建要五分钟以上,CI流水线经常因为构建超时而失败。

重构的思路

重构之前,我们先明确了几个原则。

第一,配置要清晰。vite.config.js要拆分成多个模块,每个模块负责一类配置,主文件只做组装。环境变量统一管理,不同环境的配置分开存放。

第二,代码要规范。目录结构要清晰,组件、hooks、工具函数、常量各归各位。编码风格统一,该用的规范要用上。

第三,性能要提升。冷启动、热更新、生产构建都要优化,目标是构建时间减半。

第四,渐进式重构。不搞大爆炸,一个模块一个模块地改,改完立即验证,保证项目随时能跑。

构建配置重构

首先处理的是vite.config.js。原来的文件有四百多行,我们把它拆成了几个部分:基础配置、开发环境配置、生产环境配置、插件配置。每个部分单独一个文件,主文件里引入组合。

插件也做了梳理。把不用的插件删掉,重复的合并,功能相似的选一个最好的保留。比如原来同时用了三个处理SVG的插件,最后只留了一个最灵活的。

环境变量的管理也重新做了。原来.env文件里什么都有,接口地址、密钥、功能开关混在一起。我们按环境拆成了.env.development、.env.staging、.env.production,每个文件里只放对应环境的变量。敏感信息不入库,通过环境变量注入。

别名配置也整理了一遍。原来有七八个别名,有的路径深到根本记不住。最后只保留了@指向src,其他的通过目录结构来组织,不用别名也能很方便地引用。

代码结构重构

目录结构是重点。我们重新规划了src下的目录:components放通用组件,views放页面组件,hooks放自定义hooks,utils放工具函数,constants放常量,types放类型定义,assets放静态资源。每个目录职责单一,找东西不用到处翻。

组件也做了拆分。原来有个两千行的大组件,里面混着模板、逻辑、样式,改一个小功能都要小心翼翼。我们把它拆成了十几个小组件,每个组件只做一件事,逻辑用hooks抽出来,组件本身只负责渲染。

hooks的整理花了不少时间。原来很多逻辑写在组件里,重复代码很多。我们把通用的逻辑抽成了hooks,比如请求、表单、防抖、权限判断这些。抽完之后组件代码量少了很多,逻辑也更清晰。

样式统一成了Tailwind CSS。原来三种写法混用,维护起来很痛苦。统一之后,样式都在类名里,不用在CSS文件和组件之间来回跳。当然,复杂的动画和特殊样式还是用CSS,不硬套Tailwind。

性能优化

配置和结构整理完之后,开始做性能优化。

冷启动方面,主要是减少预构建的依赖。原来把很多不需要预构建的包也加进去了,启动的时候要处理一大堆东西。清理之后,冷启动时间从一分多钟降到了二十秒。

热更新方面,发现是因为有些组件没有正确使用HMR API,导致每次修改都整页刷新。修正之后,热更新基本能做到秒级响应,改样式几乎是即时的。

生产构建的优化空间最大。我们做了代码分割,把第三方库单独打包,业务代码按路由分割。图片和字体做了压缩,大图片改成了WebP格式。还加了gzip和brotli压缩,构建产物的体积小了将近一半。

构建时间从五分钟降到了两分半,虽然还不够理想,但已经能接受了。后续还可以继续优化。

TypeScript的引入

重构的时候我们顺便把项目从JavaScript迁移到了TypeScript。这个决定一开始有争议,有人觉得增加了学习成本,会拖慢进度。

但迁移完之后发现很值。类型检查帮我们发现了好几个隐藏的bug,编辑器的智能提示也让开发效率提升了不少。虽然写类型的时候多花了一点时间,但调试和维护的时间省了很多。

迁移是渐进式的。先把新文件用TS写,老文件慢慢改。遇到类型复杂的地方,先用any顶着,后面再细化。整个过程没有影响正常的业务开发。

重构后的变化

最直观的变化是开发体验好了。冷启动快了,热更新灵了,改代码不用等半天。目录结构清晰了,找文件不用到处翻。新人入职,看半天就能上手,不用像以前那样要老员工带着读一周代码。

构建时间减半,CI流水线不再经常超时。代码质量也提升了,类型检查和ESLint把很多低级错误挡在了提交之前。线上bug少了,加班修bug的情况也少了。

团队的心情也好了。以前面对一堆烂代码,大家都不想碰,能绕就绕。现在代码结构清晰,改起来有成就感,反而愿意主动优化了。

几点经验

第一,重构要趁早。代码刚有点坏味道的时候就收拾,成本最低。等到积重难返的时候,重构的风险和成本都会高很多。

第二,不要一次改太多。小步快跑,每次改一个模块,改完立即测试提交。这样出了问题容易定位,也不会因为改动太大而不敢继续。

第三,工具很重要。ESLint、Prettier、Stylelint这些工具要配上,把规范交给工具来保证,比靠人自觉靠谱得多。

第四,重构不是一次性的。代码在不断变化,今天的优雅代码明天可能又变丑了。把重构当成日常习惯,随时顺手收拾,就不会再积累到需要大动干戈的地步。

Vite 4.0给了我们很好的构建基础,但工具再好,代码写得乱也白搭。好的项目结构和编码习惯,才是项目长期可维护的根本。