性能调优← 返回文章列表
协作平台构建体积优化:ECharts 按需引入与构建分包
记录中后台平台打包体积治理过程:通过 ECharts 按需注册模块、构建期图片压缩与 Vite manualChunks 拆包策略,缩减首屏传输体积。
LJ
· 8 分钟
本页目录展开 / 收起
读完你能做什么
- 从构建报告中找出大依赖、重复模块和不合理分包。
- 对 ECharts 与静态图片分别采用按需注册和合适的资源格式。
- 用首屏请求与缓存命中验证拆包是否真正改善加载。
不要先改 manualChunks。先记录入口包、异步包和资源体积,再判断问题属于“引入过多”“压缩不足”还是“缓存边界不稳定”。拆成更多文件不一定更快,它也会增加请求与调度成本。
在敏捷协作平台开发初期,随着燃尽图、工时分布等图表以及富文本编辑器和数据导出模块的陆续接入,生产构建产物(Bundle)体积增长至 7.2 MB。
这导致初次访问时需要下载近 8MB 的静态资源,弱网环境下白屏时间明显拉长。本文记录具体的排查方式与逐步瘦身的过程。
体积瓶颈分析
通过 rollup-plugin-visualizer 开启产物分析矩阵,发现主要体积由三大块构成:
7.2 MB 产物解剖图谱:
┌───────────────────────────────────────────────────────────┐
│ 1. ECharts 全量全功能包 (占 2.4 MB) ──► 绝大部分图表用不上 │
│ 2. 静态 UI 演示图与高清 PNG (占 2.8 MB) ──► 零压缩 │
│ 3. 单一大文件 Vendor Bundle (占 2.0 MB) ──► 缓存命中率极低 │
└───────────────────────────────────────────────────────────┘ECharts 按需引入与模块注册
习惯直接写 import * as echarts from 'echarts' 会把 3D 图表、GL 渲染器、树图等所有无关模块全部打包进产物。
改造为按需注册核心模块:
// lib/echarts.ts
import * as echarts from 'echarts/core';
import { BarChart, LineChart, PieChart } from 'echarts/charts';
import {
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent,
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
// 仅注册本项目实际用到的图表类型与通用组件
echarts.use([
BarChart,
LineChart,
PieChart,
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent,
CanvasRenderer,
]);
export default echarts;- 收益:ECharts 体积从 2.4MB 减少到 420KB,体积下降超过 80%。
静态资源构建期压缩
在构建流水线中引入 vite-plugin-image-optimizer:
// vite.config.ts
import { defineConfig } from 'vite';
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer';
export default defineConfig({
plugins: [
ViteImageOptimizer({
png: { quality: 80 },
jpeg: { quality: 80 },
webp: { quality: 85 },
svg: {
plugins: [
{ name: 'removeViewBox', active: false },
{ name: 'sortAttrs', active: true },
],
},
}),
],
});- 收益:全站图片体积从 2.8MB 缩减至 480KB。
Vite 分包策略(manualChunks)
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
'react-vendor': ['react', 'react-dom'],
'echarts-vendor': ['echarts/core', 'echarts/charts', 'echarts/components'],
'mobx-vendor': ['mobx', 'mobx-react-lite'],
'query-vendor': ['@tanstack/react-query'],
},
},
},
chunkSizeWarningLimit: 600,
},
});优化前后数据对比
| 评估维度 | 优化前 | 优化后 | 改善幅度 |
|---|---|---|---|
| 总构建体积 | 7.2 MB | 1.15 MB | -84.0% |
| Gzip 传输体积 | 2.1 MB | 310 KB | -85.2% |
| 首屏加载白屏时间 (FCP) | 6.2 秒 | 0.8 秒 | -87.1% |
| Lighthouse 性能跑分 | 38 分 | 95 分 | +57 分 |
官方资料
工程经验小结
分包并非拆得越细越好。过细的 manualChunks 会导致浏览器发起过多的并发 HTTP 请求,反而可能在 HTTP/1.1 或弱网高延迟环境下恶化加载瀑布流。
拆包的核心在于区分变动频率低的基础运行时(如 react、mobx)与高频迭代的业务逻辑,让长期缓存真正发挥作用。同时,静态图片在进入仓库前最好有统一的尺寸和格式规范,单纯依赖构建期插件压缩仍可能掩盖非必要的超大原图引入问题。