Advanced (更新: 2026/6/2)

用 Claude Code 做 JavaScript Bundle 分析实战指南

用 Claude Code 分析 Vite/Astro/Next 打包体积、重复依赖、动态导入与 CI 预算。

用 Claude Code 做 JavaScript Bundle 分析实战指南

JavaScript bundle 变重,通常不是因为一次明显的错误,而是因为很多合理需求慢慢叠加:图表、富文本编辑器、日期库、地图、视频播放器、A/B 测试代码、认证 SDK。问题不在于这些功能不该做,而在于它们经常被一起发给了第一次打开页面的用户。

Bundle 分析就是检查生产构建后真正发给浏览器的 JavaScript 和 CSS。用更直白的话说,就是先称行李有多重,再打开箱子看是哪几件东西最占重量。Claude Code 可以帮你读报告、找依赖、改代码、写 CI,但前提是你给它明确的测量流程,而不是只说“帮我优化性能”。

本文面向 Vite、Astro、Next.js 类项目,覆盖 rollup-plugin-visualizersource-map-explorer、重复依赖检查、dynamic import、CI bundle budget 和 Claude Code review。相关基础可以继续看 代码分割tree shaking性能优化

工作流先固定

分析时常见的数字有 raw、gzip、brotli。raw 是压缩前大小,适合看 treemap;gzip 和 brotli 更接近真实网络传输。不要只盯一个数字,因为有些库压缩后不大,但解析和执行仍然耗时。

flowchart LR
  A["production build"] --> B["visual report"]
  B --> C["duplicate packages"]
  C --> D["replace or dedupe"]
  B --> E["route-level split"]
  D --> F["bundle budget in CI"]
  E --> F
  F --> G["Claude Code review"]

官方资料要作为判断依据:Vite 的 Building for Production、Astro 的 Analyze bundle size、Next.js 的 Package Bundling、web.dev 的 Performance budgets 101,以及 Claude Code 官方概览

可视化 Vite 和 Astro

Vite 项目可以先安装 rollup-plugin-visualizer。它会生成一个 HTML treemap,显示每个依赖在构建产物中的占比。

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

export default defineConfig({
  plugins: [
    visualizer({
      filename: "dist/bundle-stats.html",
      template: "treemap",
      gzipSize: true,
      brotliSize: true,
      open: false
    })
  ],
  build: {
    sourcemap: true,
    rollupOptions: {
      output: {
        manualChunks: {
          react: ["react", "react-dom"],
          charts: ["recharts"],
          editor: ["@tiptap/react", "@tiptap/starter-kit"]
        }
      }
    }
  }
});

Astro 里放到 vite 配置下:

// astro.config.mjs
import { defineConfig } from "astro/config";
import { visualizer } from "rollup-plugin-visualizer";

export default defineConfig({
  vite: {
    plugins: [
      visualizer({
        filename: "dist/bundle-stats.html",
        template: "treemap",
        gzipSize: true,
        brotliSize: true
      })
    ],
    build: { sourcemap: true }
  }
});
npm run build
open dist/bundle-stats.html

Windows PowerShell 使用:

start dist/bundle-stats.html

报告中优先寻找首屏不需要的内容:图表库、管理后台编辑器、地图、视频播放器、Markdown 转换器、过大的日期库、只在后台使用的 UI。

读取 source map 和 Next.js 报告

source-map-explorer 能根据 JS 文件和 source map 展示最终 bundle 的来源。Vite 中先开启 sourcemap: true,再执行:

npm install -D source-map-explorer
npm run build
npx source-map-explorer "dist/assets/*.js" --html dist/source-map-report.html

Next.js 项目要先确认当前版本和构建器,再选择官方 bundle analyzer 或 @next/bundle-analyzer。不要把旧 webpack 教程直接复制到 Turbopack 项目里。

// next.config.mjs
import bundleAnalyzer from "@next/bundle-analyzer";

const withBundleAnalyzer = bundleAnalyzer({
  enabled: process.env.ANALYZE === "true"
});

export default withBundleAnalyzer({
  reactStrictMode: true
});
npm install -D @next/bundle-analyzer
ANALYZE=true npm run build

重复依赖检查

大库容易被看到,重复依赖更容易漏掉。比如 date-fns 同时存在两个主版本,或者 lodashlodash-es 混用,都会让 bundle 变胖。

npm ls date-fns lodash lodash-es
npm dedupe

pnpm 项目:

pnpm why date-fns
pnpm dedupe

给 Claude Code 的请求要把调查和修改分开:

请分析本仓库的生产 bundle。
1. 根据 dist/bundle-stats.html 或 source-map-explorer 输出列出重依赖
2. 用 npm ls 或 pnpm why 检查重复包
3. 把候选项分成 replace、dedupe、dynamic import、remove
4. 保留现有 UI、SEO 文本、CTA 和 analytics 事件
5. 做最小安全修改,并运行 npm run build 与 bundle budget 检查
原因处理方式合并前检查
moment 全站加载改用 Intl.DateTimeFormat 或小型工具时区和语言
整包导入 lodash改成函数级导入或原生 APIESM/CommonJS 混用
后台编辑器很重点击后或后台路由再加载loading 与错误状态
图表库进首页分离到报表页面响应式布局
依赖多版本dedupe 或对齐版本peer dependency

用 dynamic import 移出首屏

dynamic import 不是让代码消失,而是把加载时机推迟到用户真正需要时。适合后台报表、富文本编辑器、地图、小概率使用的弹窗。

// src/features/reports/ReportsButton.tsx
import { useState } from "react";

export function ReportsButton() {
  const [html, setHtml] = useState<string>("");
  const [loading, setLoading] = useState(false);

  async function handleClick() {
    setLoading(true);
    const { renderRevenueReport } = await import("./renderRevenueReport");
    setHtml(renderRevenueReport([12000, 18400, 9300]));
    setLoading(false);
  }

  return (
    <section>
      <button type="button" onClick={handleClick} disabled={loading}>
        {loading ? "生成报表中" : "显示收入报表"}
      </button>
      <output aria-live="polite">{html}</output>
    </section>
  );
}
// src/features/reports/renderRevenueReport.ts
export function renderRevenueReport(values: number[]): string {
  const total = values.reduce((sum, value) => sum + value, 0);
  return `本月合计: ${new Intl.NumberFormat("zh-CN").format(total)} 元`;
}

Next.js 中,搜索需要的正文、价格、购买按钮、咨询 CTA 应保持服务端输出,只延迟后台编辑器:

// app/admin/EditorSlot.tsx
"use client";

import dynamic from "next/dynamic";

const RichEditor = dynamic(() => import("./RichEditor"), {
  ssr: false,
  loading: () => <p aria-live="polite">正在加载编辑器...</p>
});

export function EditorSlot() {
  return <RichEditor initialMarkdown="# Draft" />;
}

在 CI 中设置预算

优化一次不够,下一次 PR 可能又会引入大依赖。把预算放进 CI,超过时必须解释原因。

// scripts/check-bundle-budget.mjs
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
import path from "node:path";
import { brotliCompressSync, gzipSync } from "node:zlib";

const targetDir = "dist/assets";
const maxTotalGzip = 220 * 1024;
const maxSingleGzip = 140 * 1024;

function walk(dir) {
  return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
    const fullPath = path.join(dir, entry.name);
    if (entry.isDirectory()) return walk(fullPath);
    return /\.(js|css)$/.test(entry.name) ? [fullPath] : [];
  });
}

if (!existsSync(targetDir)) {
  console.error(`Missing ${targetDir}. Run npm run build first.`);
  process.exit(1);
}

const rows = walk(targetDir).map((file) => {
  const content = readFileSync(file);
  return {
    file,
    raw: statSync(file).size,
    gzip: gzipSync(content).byteLength,
    brotli: brotliCompressSync(content).byteLength
  };
});

const totalGzip = rows.reduce((sum, row) => sum + row.gzip, 0);
const tooLarge = rows.filter((row) => row.gzip > maxSingleGzip);

if (totalGzip > maxTotalGzip || tooLarge.length > 0) {
  console.error(`Bundle budget failed. total gzip=${totalGzip} bytes`);
  process.exit(1);
}

console.log(`Bundle budget passed. total gzip=${totalGzip} bytes`);
# .github/workflows/bundle-budget.yml
name: Bundle Budget
on: [pull_request]
jobs:
  bundle-budget:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm run build
      - run: node scripts/check-bundle-budget.mjs

初始预算不要设成理想值。先用当前 gzip 结果加约 10% 余量,超过时要求 PR 说明增加原因、影响页面和替代方案。

真实使用场景

第一,SaaS 管理后台。普通用户需要列表、搜索、导航和主要 CTA;管理员才用的图表、审计日志、CSV 导出、账单报表可以拆到独立 chunk。给 Claude Code 指定只改 src/features/admin,避免误改认证和导航。

第二,内容站或课程站。正文、标题、购买链接和咨询 CTA 应尽早显示;Markdown 预览、图片裁剪、活动管理后台可以延迟。这里的性能直接影响广告曝光、联盟链接和咨询转化。可以结合 analytics 实装 一起验证。

第三,带地图、视频、计算器或诊断表单的落地页。首屏保留价值主张、价格、证据和行动按钮,重组件在滚动或点击后加载。媒体 UI 可继续参考 视频播放器可访问性实现

第四,内部 UI 包。@company/ui 顶层导入可能让 Button 顺带带入 DatePicker、Modal、Chart 和整套图标。应拆分 exports,并明确 CSS、主题初始化等副作用。

常见失败

不要用 dev build 判断体积。Vite dev server、HMR、未压缩代码都不能代表生产 bundle。也不要切得太碎,很多小 chunk 会增加请求和等待时间。source map 只适合分析和错误追踪,公开到 CDN 前要评估安全风险。manualChunks 也不能一劳永逸,依赖升级后要重新看是否还合理。

实施后让 Claude Code 做第二轮 review:

请从 bundle 分析角度 review 这个 PR:
- 首屏依赖是否仍然必要
- 是否存在重复包版本
- dynamic import 是否有 loading 和错误状态
- SEO 文本、价格、CTA、analytics 是否没有被延迟
- bundle budget 失败日志是否能帮助开发者定位原因
- 总结 npm run build 结果和报告路径

收益导线

Bundle 分析不是纯技术整理。首屏更快,正文、商品链接、免费资料和咨询 CTA 就更早出现。对 ClaudeCodeLab 这类内容站来说,它会影响广告收入、模板购买和培训咨询。

个人练习可以从 免费速查表 开始,需要模板时看 产品列表。团队如果要一起整理 Vite、Astro、Next.js、CLAUDE.md、CI 预算和 review 规则,可以从 Claude Code 培训与咨询 进入。

实际验证结果

本文示例按 Vite/React 风格检查过:visualizer 会输出 HTML 报告,source-map-explorer 需要 source map,Node 预算脚本只用内置 fspathzlib。实际项目中最有效的不是盲目替换所有大库,而是先区分“首屏必须出现”和“可以稍后加载”。富文本编辑器和图表通常值得拆,正文、价格、购买链接和咨询 CTA 通常不该延迟。

总结

可靠的 Claude Code bundle 优化从证据开始:生产构建、可视化、重复依赖检查、动态导入、CI 预算、二次 review。Bundle analysis、tree shaking、code splitting 不是三件孤立任务,而是让产品在流量增长后仍保持速度和转化的同一套工程流程。

#Claude Code #bundle analysis #Webpack #Vite #performance
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。