【阶段2收官】day93-bundle-optimization

作者:mario 发布时间: 2026-09-04 阅读量:4 评论数:0

Day 93 · 产物优化 — bundle 分析与首屏瘦身:数字说话的收官

昨天上线成功,今天给它"称重":bundle 可视化分析找出体积大头、按需引入审计揪出漏网的整包 import、首屏指标建立优化前后的量化对比。今天的原则是"预算制"——设定目标、达标即停,不追求极致(优化兔子洞是收官周最大的时间黑洞)。


目录


一、bundle 可视化分析

1.1 安装与配置

npm install -D rollup-plugin-visualizer
// vite.config.ts
import { visualizer } from "rollup-plugin-visualizer";

export default defineConfig({
  plugins: [
    vue(),
    // 构建时生成 stats.html(打开即见各模块体积占比的可交互图)
    visualizer({ open: true, gzipSize: true, filename: "stats.html" }),
  ],
});
npm run build   # 自动打开 stats.html——太阳图里每一块都是体积

1.2 读图要点(预期的大头)

预期分布(优化前的典型形态):
  echarts        —— 800KB+(若整包引入)/ 300KB(按需后)
  vue 全家桶     —— ~100KB(runtime + router + pinia)
  业务代码       —— <100KB(三屏 + 组件)
佐证懒加载生效:三屏应是独立 chunk(Day 78 的成果)

二、ECharts 按需引入审计

2.1 最常见的漏网现场

第 8 周按需注册过(Day 53),但 Vue 迁移时容易把注册模块写成整包:

// ❌ 审计目标:这种写法把整包拉进 bundle
import * as echarts from "echarts";

// ✅ 正确:按需注册模块(第 8 周的 echarts-custom.ts 原样迁入)
// src/core/echarts-custom.ts
import * as echarts from "echarts/core";
import { LineChart, BarChart, GaugeChart, RadarChart } from "echarts/charts";
import { GridComponent, TooltipComponent, LegendComponent, MarkLineComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";

echarts.use([
  LineChart, BarChart, GaugeChart, RadarChart,
  GridComponent, TooltipComponent, LegendComponent, MarkLineComponent,
  CanvasRenderer,
]);
echarts.registerTheme("industrial-dark", INDUSTRIAL_DARK_THEME);   // Day 55 主题

export default echarts;   // 全工程只从这里 import

2.2 审计方法

1. 全局搜索 from "echarts"(不带 /core 的裸包 import)——逐个改为 echarts-custom
2. VChart 组件(Day 76)的 import 源核对
3. 类型引用检查:EChartsOption 从 "echarts" import 类型是安全的
   (纯类型编译后消失,不进 bundle)

审计收益预期:整包 → 按需通常省 500KB+(gzip 后 ~150KB),是今天最大的一刀。


三、manualChunks:手动分包策略

3.1 为什么要手动分包

Vite 默认分包较粗(一个 vendor 大块)。大屏的加载策略值得手动控制:

// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          // 策略:稳定的大依赖独立分块——利用浏览器长缓存
          if (id.includes("echarts")) return "echarts";
          if (id.includes("node_modules")) return "vendor";
          // 业务代码不干预:三屏已由路由懒加载自动分包(Day 78)
        },
      },
    },
  },
});

3.2 分包的缓存逻辑

发版后:
  vendor-abc123.js   内容没变 → hash 没变 → 用户浏览器直接用缓存 ✅
  index-def456.js    业务变了 → hash 变 → 重新下载(只下载这个小块)
不分包时:任何改动 → 整个大包重新下载

这也是面试题:“你们怎么优化首屏/缓存?”——懒加载(Day 78)+ 按需(今天)+ 分包(今天)三件套是完整答案。


四、首屏指标与优化对比

4.1 指标采集

# Lighthouse(Chrome DevTools 自带):
# 对线上地址跑 Performance 审计(移动端模拟模式)

4.2 优化前后对比表(今天的主产出)

指标 优化前 优化后 说明
总产物体积 ___ ___ dist 文件夹
首屏 chunk(index + vendor) ___ ___ 懒加载的屏不算
echarts chunk ___ ___ 按需审计的收益
gzip 后首屏 ___ ___ 传输体积
FCP(首次内容绘制) ___ ___ Lighthouse
LCP(最大内容绘制) ___ ___ 大屏首屏=屏 A
TTI(可交互时间) ___ ___ 轮播启动

填表纪律:优化前数据先采集(改一行代码之前)——没有基线的优化是自嗨。


五、优化预算与止损纪律

5.1 本周的预算制

达标线(够了就停):
  □ 首屏(含 vendor)gzip ≤ 200KB
  □ echarts chunk gzip ≤ 120KB(按需后合理区间)
  □ LCP ≤ 2.5s(普通网络移动端)
超出预算才继续挖;达标立即转 Day 94 的资产工作

5.2 明确不做的优化(记录原因,防未来乱入)

✗ Tree-shaking 骚操作/极致压缩——边际收益 < 维护成本
✗ SSR/SSG——大屏无 SEO 需求,纯负收益
✗ Web Worker 拆数据链路——当前数据量(20 设备 2s 快照)远未到瓶颈
✗ Map 深侦听换引用方案(Day 81 遗留)——触发条件未到(设备 > 50),
  写清阈值进待办即可(Day 85 边界文档的复审条件节)

"不做什么"的清单与"做了什么"同样有说服力——止损判断力是工程成熟度的标志。


六、常见坑点

坑 1:类型 import 混淆导致整包误判

import type { EChartsOption } from "echarts" 是纯类型(安全);import { EChartsOption } from "echarts"(无 type)在 verbatimModuleSyntax 关闭时会拉运行时。规范:类型一律 import type

坑 2:manualChunks 切太碎

每个 npm 包一个 chunk → 请求数爆炸(HTTP/1.1 场景更糟)。粒度原则:只拆"大且稳定"的依赖(echarts 级别),小的归 vendor。

坑 3:优化后路由懒加载失效

manualChunks 把屏组件错误归入大块(判断条件写宽了)→ 三屏 chunk 消失。验证:build 输出里 ScreenA/B/C 的独立 js 仍在。

坑 4:只看体积不看加载时序

首屏 chunk 小了但被 waterfall 阻塞(CSS/字体阻塞渲染)。Lighthouse 的 Opportunities 面板会指路——体积是手段,指标是目的

坑 5:本地 Lighthouse 数据当真

本机网络/性能偏好影响跑分。以线上地址 + 无痕窗口 + 三遍取中位为准(Day 84 跑分纪律的延伸)。


七、自测挑战

T1 · 分析与审计(60 分钟)

完成第一至二节:stats.html 生成、整包 import 全部清剿、echarts chunk 体积达标。

T2 · 分包与对比表(50 分钟)

完成第三至四节:manualChunks 生效(hash 稳定性验证:改业务代码重 build,vendor hash 不变)、优化前后对比表填满。

T3 · 止损自评(10 分钟)

对照 5.2 的"不做清单",检查自己有没有掉进兔子洞(超预算还在挖)——写下你今天的止损点,这是给自己交付纪律的存证。


八、总结

环节 要点
可视化 visualizer 太阳图——先看再动
按需审计 裸包 import 清剿,只从 echarts-custom 进
分包 大而稳定的依赖独立——hash 缓存红利
基线 优化前先采集,对比表是主产出
预算制 达标即停 + "不做"清单——止损判断力

数字达标了。明天把数字和画面一起装进 README:演示资产更新日。

评论