Front-End-Checklist 性能预算实战:用 size-limit 与 Lighthouse CI 在 CI 中强制执行
2026/9/19 13:58:57 网站建设 项目流程

Front-End-Checklist 性能预算实战:用 size-limit 与 Lighthouse CI 在 CI 中强制执行

【免费下载链接】Front-End-Checklist🗂 The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist

性能预算是作用于可度量指标上的显式约束,一旦超出就会直接导致 CI 构建失败。本文以 Front-End-Checklist 仓库中performance-budget规则为核心,完整讲解如何用 size-limit 设定包体积预算、用 Lighthouse CI 断言运行时指标(LCP/TBT/CLS)、如何渐进收紧阈值,以及如何用生产环境 RUM(真实用户监控)补全 CI 之外的最后一块拼图。读完你可以在自己的项目中落地一套"PR 合入即拦截性能回退"的完整流水线。

什么是性能预算:为什么"没有预算"等于"注定退化"

在 Front-End-Checklist 的规则体系中,性能预算(performance budget)被明确定义为:

Performance budgets are explicit constraints on measurable metrics that fail your build when exceeded.(性能预算是对可度量指标的显式约束,一旦超出就会使构建失败。)

这个定义的三个关键词缺一不可:

  • 可度量(measurable):预算必须挂在可量化的指标上,例如最大包体积、最低 Lighthouse 分数、最大 LCP 时间,而不是"页面要快一点"这种无法验证的描述;
  • 显式(explicit):阈值必须写成配置文件、纳入版本控制,是可审查、可讨论的团队约定;
  • 失败(fail your build):这是与普通告警的本质区别——超出预算不是打印一行警告,而是让 CI 直接变红,从机制上阻止回退合入。

规则文件 packages/content/rules/en/testing/performance-budget.mdx 与技能文档 skills/performance-budget/references/rule.md 给出了不设预算的后果画像:

没有自动化强制时,性能会逐渐退化——每个 PR 加一个小库、每个功能多几 KB,几个月后原本 2 秒加载的应用变成 5 秒。性能预算让回退在 PR 阶段就暴露,而不是等到用户投诉。在评审时发现"这个 PR 给 bundle 增加了 200KB"远比事后调试一个缓慢的生产站点便宜。

这套规则位于testing分类下(对应 skills/performance-budget/SKILL.md 中的category: testing,优先级 medium、难度 intermediate、预估耗时 25 分钟),它的aiContext特别点明了使用时机与关键区分:

在审查 CI 配置、bundle 分析工作流,或给 PR 新增依赖与资源时使用。要区分包体积预算(bundle-size budgets)与运行时预算(runtime budgets,如 Lighthouse 或 Core Web Vitals),两者都要强制执行。

这个区分是全文的主线:size-limit 管"下载多少字节",Lighthouse CI 管"跑起来多快",二者互补而非替代。

快速参考:预算体系的核心要点

技能文档 skills/performance-budget/SKILL.md 的 Quick Reference 浓缩了整个方法论:

  • 定义具体阈值:最大 bundle 大小、最低 Lighthouse 分数、最大 LCP 时间;
  • 超出预算就让 CI 失败:以此防止性能回退;
  • 两类预算分工明确:体积预算捕获意外引入的重依赖;Lighthouse 预算捕获运行时回退;
  • 先松后紧:从宽松的预算起步,随着优化逐步收紧;
  • 监控生产 RUM:让回退在部署后也能被发现,而不仅仅依赖 CI。

这五条对应了后面每一个实操小节,可以作为落地清单使用。

方案一:用 size-limit 设包体积预算

体积预算的目标是捕获"意外重依赖"——某位开发者为了一个小功能引入了一个 300KB 的库,或者构建产物悄悄膨胀。size-limit 会把这个问题变成 CI 红叉。

安装与配置

pnpm add -D size-limit @size-limit/preset-app

package.json中声明预算与脚本(完整示例见 packages/content/rules/en/testing/performance-budget.mdx):

{ "size-limit": [ { "name": "Main bundle", "path": "dist/assets/index-*.js", "limit": "200 kB", "gzip": true }, { "name": "CSS", "path": "dist/assets/index-*.css", "limit": "30 kB", "gzip": true }, { "name": "Vendor chunk", "path": "dist/assets/vendor-*.js", "limit": "150 kB", "gzip": true } ], "scripts": { "size": "size-limit", "analyze": "size-limit --why" } }

各配置项的作用:

配置项含义取值建议
name预算条目的显示名,用于 CI 输出可读性语义化命名,如 "Main bundle"、"CSS"
path用 glob 匹配要测量的构建产物以实际构建输出目录为准,Vite 默认dist/assets/
limit体积上限配合gzip: true时以 gzip 后字节计
gzip是否按 gzip 压缩后体积计算首屏 JS 建议开启,更贴近真实网络传输
--why生成体积分析报告,定位膨胀来源analyze脚本调用,配合 Webpack Bundle Analyzer / Rollup Visualizer 使用

接入 CI

# .github/workflows/size-check.yml - name: Check bundle size run: | pnpm build npx size-limit

规则文档特别提醒:先执行构建(pnpm build)再跑size-limit,因为 size-limit 测量的是真实构建产物,而不是源码目录。

结合仓库规则理解:体积预算的上游手段

体积预算不是孤立存在的。Front-End-Checklist 在 packages/content/rules/en/testing/performance-budget.mdx 中显式声明了关联规则(relatedRules),其中第一条就是:

  • code-splitting:代码分割是保持在包体积预算内的首要技术。

packages/content/rules/en/javascript/code-splitting.mdx 从实现侧支撑了这一点:通过import()动态导入把大库移出初始依赖图、按路由拆分 chunk、对图表库/富文本编辑器等重型组件懒加载。该规则的验证节更是把预算直接写成了验收标准:

If your project uses a JS budget, keep the initial bundle within that threshold rather than only moving bytes into slightly later chunks; a common starting point is<= 150 KBgzipped for the main route bundle.(如果项目启用了 JS 预算,让初始 bundle 保持在阈值内,而不是仅仅把字节挪到稍晚的 chunk 中;常见起点是主路由 bundle gzip 后<= 150 KB。)

这正是"预算驱动架构决策"的典型体现:设定预算后,代码分割不再是可选项,而是达到预算的必要手段。仓库中 packages/content/rules/en/performance/page-weight.mdx 的"JavaScript Bundle Optimization"一节也给出了同款 VitemanualChunks拆分策略,可互为印证。

方案二:用 Lighthouse CI 断言运行时指标

体积预算回答"传了多少字节",运行时预算回答"用户体验到底行不行"。Lighthouse 在一个受控的 Chrome 实例中加载页面,产出 Performance / Accessibility 等类别分数以及 LCP、TBT、CLS 等 Web Vital 指标,Lighthouse CI 让这些指标可以成为断言。

安装

pnpm add -D @lhci/cli

配置断言(lighthouserc.json)

完整示例见 packages/content/rules/en/testing/performance-budget.mdx:

{ "ci": { "collect": { "url": ["http://localhost:3000", "http://localhost:3000/about"], "numberOfRuns": 3 }, "assert": { "assertions": { "categories:performance": ["error", { "minScore": 0.8 }], "categories:accessibility": ["error", { "minScore": 0.9 }], "first-contentful-paint": ["warn", { "maxNumericValue": 2000 }], "largest-contentful-paint": ["error", { "maxNumericValue": 2500 }], "total-blocking-time": ["error", { "maxNumericValue": 300 }], "cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }] } }, "upload": { "target": "temporary-public-storage" } } }

配置要点:

  • collect.url:对哪些页面做审计。规则文档以首页加一个代表页(/about)为例——不要只测一个页面,路由差异可能让某些页面悄悄超预算;
  • numberOfRuns:多次运行取中位数,降低偶发波动导致的误报;规则示例用 3 次;
  • assertions的二维语法:每项断言是["级别", { 阈值 }]error级别会让 CI 失败,warn级别只输出告警。注意这里巧妙地示范了分级策略——FCP 先用warn(2000ms 上限)观察,LCP/TBT/CLS 用error直接卡死,与"先松后紧"的原则一脉相承;
  • upload.target: "temporary-public-storage":把审计报告上传到临时公开存储,便于在 CI 产物中回看完整 Lighthouse 报告。

接入 CI

# .github/workflows/lighthouse.yml - name: Run Lighthouse CI run: | pnpm build npx lhci autorun

lhci autorun会依次执行 collect(启动本地服务器、跑审计)、assert(比对断言)、upload(上传报告)三个阶段。

体积与运行时预算的分工(aiContext 的核心区分)

两条流水线各司其职,缺一不可:

维度size-limitLighthouse CI
度量对象构建产物字节数真实浏览器中的运行时行为
捕获问题意外重依赖、产物膨胀渲染性能、可访问性、布局稳定性
失败粒度按文件/chunk 精确到 KB按页面 + 指标阈值
典型阈值gzip 后 KB 数分数(0–1)与毫秒/秒级数值

单独看任何一个都会漏:体积没超但存在巨大同步脚本阻塞主线程,Lighthouse 分数照样崩;Lighthouse 全绿但新增了 200KB 依赖,体积预算会兜底抓住。这就是 skills/performance-budget/SKILL.md 中 "Size budgets catch accidental heavy dependencies; Lighthouse budgets catch runtime regressions" 的完整含义。

方案三:用 Lighthouse budget.json 做资源级预算

除了 Lighthouse CI 的指标断言,Lighthouse 本身还支持按资源类型设预算,规则文档给出了独立的budget.json

[ { "path": "/*", "resourceSizes": [ { "resourceType": "script", "budget": 250 }, { "resourceType": "image", "budget": 500 }, { "resourceType": "total", "budget": 1600 } ] } ]

path用 glob 匹配路由(/*表示所有页面),resourceSizes按资源类型(script、image、total 等,单位为 KB)设定上限。它可以作为页面维度的"资源重量"审计:把脚本总量卡在 250KB、图片总量卡在 500KB、整页卡在 1600KB。这条线索与 packages/content/rules/en/performance/page-weight.mdx 的"页面重量预算"规则直接呼应——该规则给出了更细粒度的重量基准表:

类别目标可接受较差
整页< 500KB< 1500KB> 1500KB
HTML< 50KB< 100KB> 100KB
CSS< 50KB< 100KB> 100KB
JavaScript< 200KB< 400KB> 400KB
图片< 200KB< 500KB> 500KB
字体< 100KB< 200KB> 200KB

该规则还解释了为什么体积预算如此重要:页面重量与加载时间直接相关——1.5MB 的页面在 4G 移动网络下需要 3–5 秒加载,其中图片通常占页面重量的 50–70%,JavaScript 是第二大贡献者(15–25%)。如果要在budget.json中落地这套基准,可以直接换算成 KB 写入resourceSizes

方案四:Webpack / Vite 构建级预算

在构建工具层面做"温和版"预算,作为 CI 硬断言之前的快速反馈环:

// vite.config.js export default { build: { rollupOptions: { output: { // Warn when chunks are large manualChunks: { vendor: ['react', 'react-dom'], ui: ['@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu'] } } }, chunkSizeWarningLimit: 500 // KB — build warns above this } }

要点:chunkSizeWarningLimit只是警告(以 KB 计,超过 500 构建输出警告),不会失败——它适合做开发者本地反馈,真正的强制交给 size-limit 或 Lighthouse CI。manualChunks手动拆包把第三方依赖集中成 vendor / ui chunk,避免每个页面都重复打包公共库。

推荐起始阈值:先有基线,再谈优化

规则文档给出了一张可直接作为第一版预算的对照表:

指标良好(Good)待优化(Needs Work)
主 JS bundle(gzip)< 150 KB> 300 KB
总 JS(gzip)< 400 KB> 800 KB
Lighthouse Performance> 80< 60
Largest Contentful Paint< 2.5s> 4s
Total Blocking Time< 200ms> 600ms
Cumulative Layout Shift< 0.1> 0.25

这些阈值同时是"预算"与"目标":把第一版预算设在"良好"与"待优化"之间的合理位置,让团队有空间推进优化,又不至于让预算形同虚设。前端领域有共识性的参考(如 Core Web Vitals 的 LCP 2.5s、CLS 0.1 阈值),仓库 packages/content/rules/en/testing/performance-budget.mdx 的 sources 元数据也记录了对应的权威出处(web.dev 的 Core Web Vitals 阈值指南与 Lighthouse CI 配置文档)。

渐进收紧:预算治理的工作节奏

预算不是"设一次就永不再动",规则文档给出了三个明确的治理原则:

  1. 从当前应用现实可达的阈值起步(Start with thresholds the current app can realistically meet)——第一版预算如果直接把所有指标钉在"良好"档,可能让 CI 全红、团队失去信心;先记录现状,再逐步逼近目标;
  2. 把稳定的告警升级为阻塞错误(Promote stable warnings to blocking errors once the team fixes obvious regressions)——这正是 Lighthouse 断言里warnerror的演进路径:先用warn观察若干天,确认没有明显误报后升级为error
  3. 重大架构变更后重新审视预算(Revisit budgets after major architectural changes)——引入新框架、切换渲染模式、重构数据层之后,预算应是团队有意为之的决策,而不是从旧架构继承来的过期数字。

Front-End-Checklist 的多篇性能规则(compression.mdx、font-loading.mdx、dom-size.mdx 等)在验证节都包含同一句标准要求:"如果该规则映射到预算或 Web Vital,确认页面现在保持在该阈值内"——这说明预算在该仓库的规则体系中扮演着统一验收闸门的角色:任何性能类修复最终都要回到预算阈值上验证是否达标。

生产 RUM 补全闭环:CI 之外的最后一道防线

这是规则文档最有价值的部分之一。CI 预算在合入前拦截回退,但字段数据(field data)捕获的是真实环境中的回退——真实设备、第三方标签、路由组合、后端波动,这些都是 CI 里受控环境覆盖不到的:

信号建议告警
LCP p75连续 3 个部署窗口高于 2.5s
INP p75较上一基线高出 200ms 以上
CLS p75发布后高于 0.1
失败路由预算端点错误率高于基线

要点解读:

  • 用 p75 而非平均值:p75 代表大多数真实用户(尤其是移动端)的体验,平均值得出的结论容易被少数快请求掩盖;
  • 对基线做相对告警(如 INP 较基线 +200ms):避免绝对阈值在季节流量、新功能发布等正常波动下误报;
  • 部署后持续观察:有些回退只有上线后在大流量和真实设备上才会暴露,这需要 RUM + 告警链路的支撑。

规则落地检查清单:从 Check 到 Code Review

技能文档 skills/performance-budget/SKILL.md 定义了 AI Agent / 工程师执行本规则的四步工作流:

  1. Check(检查):项目是否定义了性能预算?检查package.json与 CI 配置中是否存在体积或 Lighthouse 阈值;
  2. Fix(修复):用 size-limit 设置包体积上限,并在 CI 流水线中加入 Lighthouse CI 断言;
  3. Explain(解释):向团队解释什么是性能预算、如何选择合适阈值、如何用 size-limit 与 Lighthouse CI 强制执行;
  4. Code Review(评审):审查 CI 工作流、package.json、Lighthouse 或包体积配置中是否有显式阈值;标记预算缺失、阈值过松(抓不住回退)、或未在 PR 上强制执行的项目;检查生产 RUM 与告警是否已接线,能在发布后检测回退。

对应地,验证工作分为自动与手动两层(见 packages/content/rules/en/testing/performance-budget.mdx 的 Verification 节):

自动化验证

  • 打开一个代表性 PR 的 CI 运行记录,确认每次变更都执行了体积与 Lighthouse 断言;
  • 验证超出阈值时流水线失败,而不是仅打印警告;
  • 把选定的预算写入版本控制,让预算变更显式、可审查。

手动验证

  • 每季度复审阈值,随着应用变好而收紧,而不是让它持续上浮漂移;
  • 每次发布后查看生产仪表盘,确认告警会在回退时触发,而不是事后有人翻日志才发现。

注意事项与环境差异

规则文档的 Support Notes 给出了两条务实的边界提醒:

  • 工具、浏览器自动化行为与 CI 环境在不同平台上可能有差异,因此要在团队实际发布和测试的目标环境中验证预期工作流;
  • 当部分受支持环境中缺少浏览器特定测试能力时,记录好回退方案(例如用 WebPageTest 等外部服务补齐 page-weight.mdx 中提到的详细资源分解审计)。

这两条的意义在于:性能预算的价值建立在结果可复现之上,环境差异导致的误报/漏报会消耗团队对预算体系的信任,提前记录回退方案能保护这套机制长期有效。

小结

性能预算把"性能不能退化"从口号变成可执行的工程约束:size-limit 守住字节,Lighthouse CI 守住运行时,budget.json 与构建工具做分级兜底,RUM 在部署后继续盯防。配合"先松后紧、定期复审、把预算写进版本控制"的治理节奏,性能回退会在 PR 阶段就被拦截,而不是等到用户投诉后再去翻生产日志。这也正是 Front-End-Checklist 将本规则归类到 testing 分类的深层原因:性能预算本质上是一套测试与验收体系,而非一次性的优化任务。

【免费下载链接】Front-End-Checklist🗂 The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询