用途
Frontend Lighthouse 是一个可移植的、框架无关的 Lighthouse CI 性能门禁(performance gate)技能。它的目标是:除非生产构建满足明确的 Core Web Vitals 预算和分类分数下限,否则阻塞每一个 Pull Request。它不是一个组件库或视觉样式,而是一个 CI 性能门禁——一份 Lighthouse CI 配置加上一个工作流。它可与 frontend-seo 和 frontend-architecture 技能配合使用:SEO 负责编写元数据,Lighthouse 证明它能快速发布。
该技能可被 Claude Code、OpenCode、Codex、Cursor、Windsurf 等读取,遵循 Anthropic SKILL.md 格式,可跨智能体移植。
核心思路
- 一份配置,一个真相来源:所有预算和断言都放在单个 lighthouserc.cjs 中,每个预算使用命名常量,断言对象里不埋魔法数字。
- 只对生产构建设门禁,绝不对开发环境:Lighthouse 针对 build + start(真实、优化后的输出)运行,开发服务器的数字对预算没有意义。
- 多次运行取中位数消除抖动:运行 3 次以上并对中位运行进行断言,使每次运行的抖动(冷缓存、CI 噪声)不会误报健康构建。
- 预算编码 Google 的“good”阈值:LCP ≤ 2500 ms,INP ≤ 200 ms(通过 TBT 实验室代理设门禁),CLS ≤ 0.1——这些是获得绿色分数的数值,而不是“需要改进”。
- 在 CI 中阻塞,并以产物形式可见:GitHub Action 对每个涉及该应用的 PR 运行门禁,并上传 HTML/JSON 报告,使失败可调试。
主要文件与安装
该技能添加以下文件:
apps/web/ (或你的应用根目录)
├── lighthouserc.cjs ← 门禁:预算 + 断言 + 收集设置
├── package.json ← "lhci": "lhci autorun --config=./lighthouserc.cjs"
└── .github/workflows/lighthouse.yml ← PR 阻塞式 CI 任务(build → start → lhci → upload)
另加一个开发依赖:@lhci/cli。
pnpm add -D @lhci/cli # 或 npm i -D / yarn add -D
配置要点(lighthouserc.cjs)
使用 .cjs(CommonJS)以便无需 ESM/TS 转译即可加载。每个预算都是带注释的命名常量,说明阈值含义。关键硬性规则:
- 每个预算都是命名常量,名称带单位(如 LCP_BUDGET_MS)和注释。
- aggregationMethod: "median-run" 不可妥协——单次运行门禁会频繁抖动。
- numberOfRuns ≥ 3(奇数给出干净的中位数)。
- 在实验室中对 INP 断言使用 TBT;将实验性的 interaction-to-next-paint 审计视为 warn 而非 error(并非每个 Lighthouse 构建都存在)。
- onlyCategories 只保留要设门禁的类别——审计更少、更快、噪声更少。
配置中定义了页面 URL 列表(MARKETING_URLS)、端口(PORT = 3100)、LCP 预算 2500 ms、INP 预算 200 ms(TBT 代理)、CLS 预算 0.1,以及类别分数下限。
严重程度与阈值选择
- largest-contentful-paint:error,≤ 2500 ms(Google “good” LCP)
- cumulative-layout-shift:error,≤ 0.1(Google “good” CLS)
- total-blocking-time:error,≤ 200 ms(INP 实验室代理)
- interaction-to-next-paint:warn,≤ 200 ms(并非所有构建都存在,不应因缺失审计而硬失败)
- categories:performance:error,≥ 0.9(顶级绿区)
- categories:seo:error,≥ 0.95(SEO 保持完美成本低)
- categories:accessibility:error,≥ 0.95(无障碍回归必须阻塞)
- categories:best-practices:error,≥ 0.9(绿区)
对必须成立的合约使用 error,对依赖环境或理想化的审计使用 warn。从严格开始,只有在记录原因后才放宽——不断抬高以求 CI 通过的预算不再保护任何东西。
使用方式
在 package.json 中添加脚本:
{
"scripts": {
"lhci": "lhci autorun --config=./lighthouserc.cjs"
}
}
lhci autorun 按顺序运行 collect → assert → upload。在推送前本地运行以复现 CI 行为:
pnpm build && pnpm lhci
# desktop form factor:
LHCI_FORM_FACTOR=desktop pnpm build && LHCI_FORM_FACTOR=desktop pnpm lhci
GitHub Actions 工作流在涉及应用路径或工作流文件的 PR 上运行,构建生产输出、运行门禁,并始终上传报告(即使失败),使红色检查可调试。工作流硬性规则:在应用路径和工作流文件上触发以使配置变更自测试;上传步骤使用 if: always();对生产构建设门禁;CI 的 Node/pnpm 版本与仓库锁定版本匹配以避免锁文件漂移。
框架适配
配置除 startServerCommand 和 startServerReadyPattern 外是框架中立的。适配示例:
- Next.js:pnpm start --port 3100(在 next build 之后),就绪模式 "Ready in"
- Remix:pnpm start(服务构建后的应用),服务器的监听日志行
- Astro:node ./dist/server/entry.mjs(SSR)或 npx serve dist(静态),适配器的就绪行 / serve 的 URL 行
- SvelteKit:node build(node 适配器),"Listening on"
- Vite SPA:npx vite preview --port 3100,"Local:"
对于纯静态输出,可跳过服务器,将 collect.staticDistDir 指向构建文件夹而非 startServerCommand——Lighthouse 内部提供服务。
调试失败或抖动运行
- LCP/TBT 抖动:提高 numberOfRuns(5),确认 median-run,确保运行器上没有其他进程争抢 CPU。
- interaction-to-next-paint 错误:它应为 warn 而非 error;某些 Lighthouse 版本缺少该审计。
- “server not ready” 超时:修正 startServerReadyPattern 以匹配框架实际就绪日志,并提高 startServerReadyTimeout。
- 真实回归:打开上传的报告产物,阅读失败审计的 “Opportunities”/“Diagnostics”,修复原因(超大图片、阻塞渲染的 JS、无尺寸媒体导致的布局偏移)——不要只是抬高预算。
- 桌面与移动分歧:运行两种形态;移动是更严格的门禁,应作为默认。
适用场景与限制
适用场景:任何 Web 前端项目,需要在 CI 中对每个 PR 强制执行 Core Web Vitals 预算和 Lighthouse 分类分数下限,且希望同一配置在本地与 CI 一致运行。
限制:INP 是字段指标,实验室中没有直接审计,需通过 TBT 代理设门禁,实验性 INP 审计仅作警告;部分审计在特定 Lighthouse 版本中可能缺失;预算需按项目实际调整,不应随意放宽。
应用与安装
将门禁加入项目:安装 @lhci/cli,放入带 URL 和 startServerCommand 的 lighthouserc.cjs,添加 lhci 脚本和工作流。在开 PR 前本地运行 pnpm build && pnpm lhci 确认通过。
将页面加入门禁:将其 URL 追加到 MARKETING_URLS(或第二个 URL 数组)。每个 URL 独立按相同预算审计。
调整预算:更改命名常量而非断言,并在注释中记录原因。优先修复回归而非抬高预算。
发布/安装此技能:保持在公共 GitHub 仓库的 skills/frontend-lighthouse/SKILL.md 中;保留 frontmatter 的 name 和高信号 description(发现索引会匹配它);使用命令安装:npx skills add <org>/<repo> --skill "frontend-lighthouse"。非 SKILL.md 智能体可从 AGENTS.md / CLAUDE.md 指向它;Kiro 可将其镜像为 steering 文件。