Vite + ant-design-vue 打包体积与开发体验优化实战

Vite + ant-design-vue 打包体积与开发体验优化实战
​Vite + ant-design-vue 打包体积与开发体验优化实战一份从「生产包 4MB 起步」到「砍掉一半、构建 4 分钟搞定」的完整优化手记。涉及按需加载、CSS-in-JS 运行时裁剪、路由级 import 链治理、dev 服务器冷启动、构建提速、配置重构。前言接手一个使用 Vite 5 + ant-design-vue 3 的中后台前端项目,产物体积和开发体验都存在明显问题。整个优化过程断断续续做了几天,走了不少弯路,最终沉淀出一套可复用的方法论。下文按问题 → 排查 → 方案 → 验证的顺序展开,重点说清楚每一步的决策理由和踩过的坑。目录问题全景阶段一:生产包全量打包治理阶段二:CSS-in-JS 运行时裁剪阶段三:dev 模式"打开页面慢"分析阶段四:定位真正的慢页面(Edge 实测)阶段五:路由级 import 链治理阶段六:生产构建提速阶段七:配置文件清理与重构方法论沉淀附录:常用工具脚本一、问题全景接手时产物体积与开发体验指标如下:| 指标 | 数值 | 状态 || ---------------------- | -------- | -------------- ||antd-iconschunk | 1.46 MB | 🐢 巨大 ||ant-design-vuechunk | 2.66 MB | 🐢 巨大 || 生产构建总耗时 | 20m 2s | 🐢 极慢 || dev 模式首次打开新业务页 | 10-30s | 🐢 慢到无法忍受 || dev 模式切换页面 | 几秒到几十秒不等 | 🐢 不可接受 || dev 模式频繁触发"重新加载" | 是 | 🐢 浏览器 HMR 反复刷 |业务规模不算小(OA管理系统,多个业务模块 + 报表 + 表单 + 富文本),但产物中显然有大量可优化空间。二、阶段一:生产包全量打包治理2.1 现象产物体积分析报告中:antd-icons-xxx.js 1.46 MB ant-design-vue-xxx.js 2.66 MB项目已经用了 unplugin-vue-components + ant-design-vue resolver 做按需引入,理论上不应该全量打包。2.2 排查:grep 找不到源头第一反应是源码里有全量 import,于是全局搜索:grep-r"from 'ant-design-vue'"srcgrep-r"import \*"src结果:没有任何显式的全量 import。没有import * from '@ant-design/icons-vue',也没有 barrel 具名导入残留。2.3 突破口:模块依赖图探针常规搜索不行,决定写一个 Rollup 插件钩子去看真实构建的模块依赖图。// debug-tools/probe-antd-imports.cjsconstantdFullEntryRegex=/ant-design-vue\/(lib|dist|es\/index|src\/index)/;constantdIconsRegex=/@ant-design\/icons-vue\/(lib|dist|es\/index|src\/index)/;exportfunctionprobeAntdFullImports(){return{name:'probe-antd-full-imports',moduleParsed(moduleInfo){if(antdFullEntryRegex.test(moduleInfo.id)||antdIconsRegex.test(moduleInfo.id)){console.log('🚨 全量入口:',moduleInfo.id);console.log(' 来自:',...moduleInfo.importedIds);}},};}把这个插件加到vite.config.js的plugins数组里再 build 一遍。结果一查一个准:🚨 全量入口: ant-design-vue/lib 来自: src/api/xxx.js 来自: src/utils/yyy.js 🚨 全量入口: ant-design-vue/lib/message 来自: src/api/zzz.js根因:有 5 个业务文件从ant-design-vue/lib(CJS 全量入口)或ant-design-vue/lib/xxx(lib 子路径)导入,绕过了按需 resolver。lib/路径是 ant-design-vue 的CommonJS 全量入口(不是 ESM 的es/),一旦从这里导入,rollup 的 tree-shake 完全失效。2.4 修复把所有ant-design-vue/lib/xxx改成ant-design-vue/es/xxx(es 是 ESM 入口,unplugin-vue-components 的 resolver 只认这一套):// ❌ 改前import{message}from'ant-design-vue/lib';importmessagefrom'ant-design-vue/lib/message';// ✅ 改后import{message}from'ant-design-vue';// 或者importmessagefrom'ant-design-vue/es/message';2.5 验证再次 build:| Chunk | 改前 | 改后 || ---------------- | ------- | ------- ||antd-icons| 1.46 MB | 0.10 MB ||ant-design-vue| 2.66 MB | 1.10 MB |antd-icons 砍掉 1.36MB,ant-design-vue 砍掉 1.56MB,与预期一致。三、阶段二:CSS-in-JS 运行时裁剪3.1 现象产物里 ant-design-vue 体积仍有 1.1MB,分析ant-design-vue-xxx.js看到:里面除了组件 JS,还塞了每个组件的 CSS-in-JS 运行时。ant-design-vue v3 用 cssinjs(@ant-design/cssinjs)做样式管理,每个组件运行时都会调用useStyleRegister注入 CSS:// ant-design-vue/es/button/index.js 简化版importuseStyleRegisterfrom'../_util/cssinjs/useStyleRegister';constuseButtonStyle=()={useStyleRegister({...},()=genStyle());// 运行时生成 CSS};业务侧早就引入了统一的ant-design-vue/dist/reset.css+ 自己抽取的custom-variables.less做主题定制,运行时 cssinjs 是冗余的。3.2 方案 A:直接关掉 CSS-in-JS 注入写一个 Vite 插件的load钩子,把每个组件的style/index.js(cssinjs 入口)替换为空 stub:// build/vite-plugins/strip-antdv-style-js.jsconstSTYLE_INDEX_REGEX=