跳到主要内容

打包产物分析与体积优化

场景

项目打包后体积过大(如 JS 超过 1MB),需要分析产物组成并优化。

分析思路

第一步:可视化分析产物

Webpack
npx webpack-bundle-analyzer stats.json

# 生成 stats.json
npx webpack --profile --json > stats.json
Vite(rollup-plugin-visualizer)
// vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
plugins: [
visualizer({
open: true,
gzipSize: true,
}),
],
});

第二步:常见体积问题与优化

问题排查方式优化手段
整个 lodash 被打包Analyzer 中看 lodash 大小lodash-es + Tree Shaking 或按路径导入
moment.js locale 全量看 locale 文件夹大小替换为 dayjs 或 IgnorePlugin
大型 UI 库全量引入看 antd/element 大小按需导入 + babel-plugin-import
未使用的代码Coverage 面板代码分割 + 懒加载
重复依赖Analyzer 中出现多次pnpm dedupe / resolutions
未压缩看 gzip 和原始大小差异开启 gzip/brotli 压缩
Source Map 泄露生产包含 .map 文件生产环境不上传 source map
按需导入示例
// ❌ 全量 — 打包整个 antd
import { Button, Table } from 'antd';

// ✅ 使用 Tree Shaking 友好的 ESM 版本
// antd v5 默认支持 Tree Shaking,确认 sideEffects 配置正确
替换重量级库
// ❌ moment.js: ~300KB
import moment from 'moment';

// ✅ dayjs: ~2KB
import dayjs from 'dayjs';

体积预算

CI 中检查包大小
// bundlesize 配置
// package.json
{
"bundlesize": [
{ "path": "dist/js/main.*.js", "maxSize": "150 kB" },
{ "path": "dist/js/vendor.*.js", "maxSize": "300 kB" }
]
}

常见面试问题

Q1: 你一般怎么分析打包产物?

答案

  1. 使用 webpack-bundle-analyzerrollup-plugin-visualizer 可视化查看
  2. 关注最大的几个模块,检查是否有全量引入、重复依赖
  3. source-map-explorer 查看具体文件占比
  4. 在 CI 中设置体积预算,超出自动告警

Q2: Tree Shaking 失效的常见原因?

答案

  1. 使用了 CommonJS(require)而非 ESM(import
  2. package.jsonsideEffects 配置不当
  3. 动态导入路径(import(variable))无法静态分析
  4. 代码中有副作用(如顶层 IIFE、全局变量赋值)
  5. Babel 把 ESM 转成了 CommonJS(检查 Babel 配置 modules: false

相关链接