协作平台构建体积优化:ECharts 按需引入与构建分包

记录中后台平台打包体积治理过程:通过 ECharts 按需注册模块、构建期图片压缩与 Vite manualChunks 拆包策略,缩减首屏传输体积。

LJ
李建辉·前端全干工程师

· 8 分钟

本页目录展开 / 收起

读完你能做什么

  • 从构建报告中找出大依赖、重复模块和不合理分包。
  • 对 ECharts 与静态图片分别采用按需注册和合适的资源格式。
  • 用首屏请求与缓存命中验证拆包是否真正改善加载。

不要先改 manualChunks。先记录入口包、异步包和资源体积,再判断问题属于“引入过多”“压缩不足”还是“缓存边界不稳定”。拆成更多文件不一定更快,它也会增加请求与调度成本。

在敏捷协作平台开发初期,随着燃尽图、工时分布等图表以及富文本编辑器和数据导出模块的陆续接入,生产构建产物(Bundle)体积增长至 7.2 MB。

这导致初次访问时需要下载近 8MB 的静态资源,弱网环境下白屏时间明显拉长。本文记录具体的排查方式与逐步瘦身的过程。


体积瓶颈分析

通过 rollup-plugin-visualizer 开启产物分析矩阵,发现主要体积由三大块构成:

TEXT
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 渲染器、树图等所有无关模块全部打包进产物。

改造为按需注册核心模块:

TS
// 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:

TS
// 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)

TS
// 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 MB1.15 MB-84.0%
Gzip 传输体积2.1 MB310 KB-85.2%
首屏加载白屏时间 (FCP)6.2 秒0.8 秒-87.1%
Lighthouse 性能跑分38 分95 分+57 分

官方资料

工程经验小结

分包并非拆得越细越好。过细的 manualChunks 会导致浏览器发起过多的并发 HTTP 请求,反而可能在 HTTP/1.1 或弱网高延迟环境下恶化加载瀑布流。

拆包的核心在于区分变动频率低的基础运行时(如 react、mobx)与高频迭代的业务逻辑,让长期缓存真正发挥作用。同时,静态图片在进入仓库前最好有统一的尺寸和格式规范,单纯依赖构建期插件压缩仍可能掩盖非必要的超大原图引入问题。

评论