我构建了一个 CLI,在发布前捕获 Lighthouse 回归。
Source: Dev.to
我构建了一个 CLI,能在代码上线前捕获 Lighthouse 回归
在过去的几周里,我在生产环境中发布了一个新功能,结果发现页面的 Performance 分数骤降。虽然功能本身工作正常,但页面加载时间明显变慢,这在用户体验和 SEO 方面都是不可接受的。
为什么选择 Lighthouse?
- 行业标准:Google 的 Lighthouse 已经成为评估网页质量(Performance、Accessibility、Best Practices、SEO 等)的事实标准。
- 可编程:它提供了 Node.js API,能够在 CI/CD 流程中自动运行。
- 可配置:可以针对不同的审计项目设置阈值,帮助团队快速定位回归。
目标
创建一个 命令行工具,在每次提交或部署前:
- 运行 Lighthouse 对指定 URL 进行审计。
- 将当前审计结果与上一次成功的基准进行比较。
- 如果任意关键指标(如
performance,accessibility)低于阈值,则阻止 CI 通过并输出详细报告。
实现概览
依赖
npm install lighthouse chrome-launcher commander chalk
- lighthouse:核心审计库。
- chrome-launcher:启动无头 Chrome 实例。
- commander:解析 CLI 参数。
- chalk:美化终端输出。
代码结构
src/
├─ index.js # 入口文件,处理 CLI 参数
├─ runner.js # 调用 Lighthouse 并返回结果
├─ comparator.js # 将新结果与基准进行比较
└─ utils/
└─ logger.js # 统一日志输出
index.js
#!/usr/bin/env node
const { program } = require('commander');
const runLighthouse = require('./runner');
const compare = require('./comparator');
const logger = require('./utils/logger');
program
.requiredOption('-u, --url <url>', '要审计的页面 URL')
.option('-b, --baseline <file>', '基准报告文件路径')
.option('-t, --threshold <json>', '阈值 JSON,例如 {"performance":90}')
.parse(process.argv);
(async () => {
const { url, baseline, threshold } = program.opts();
const result = await runLighthouse(url);
const diff = compare(result, baseline, JSON.parse(threshold || '{}'));
if (diff.failed) {
logger.error('⚠️ 检测到回归!');
logger.error(diff.message);
process.exit(1);
} else {
logger.success('✅ 没有发现回归。');
process.exit(0);
}
})();
注意:以上代码块保持原样,不进行翻译。
runner.js
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
module.exports = async function runLighthouse(url) {
const chrome = await chromeLauncher.launch({chromeFlags: ['--headless']});
const options = {output: 'json', port: chrome.port};
const runnerResult = await lighthouse(url, options);
await chrome.kill();
return runnerResult.lhr;
};
comparator.js
const fs = require('fs');
module.exports = function compare(current, baselinePath, thresholds) {
const baseline = baselinePath ? JSON.parse(fs.readFileSync(baselinePath, 'utf-8')) : null;
const diffs = [];
// 只比较用户提供阈值的指标
for (const [key, minScore] of Object.entries(thresholds)) {
const currentScore = current.categories[key].score * 100;
if (currentScore < minScore) {
diffs.push(`${key} 分数 ${currentScore} < ${minScore}`);
}
}
// 如果提供了基准文件,还会比较每个指标的变化幅度
if (baseline) {
for (const category of Object.keys(current.categories)) {
const cur = current.categories[category].score * 100;
const base = baseline.categories[category].score * 100;
if (cur < base) {
diffs.push(`${category} 分数下降: ${base} → ${cur}`);
}
}
}
return {
failed: diffs.length > 0,
message: diffs.join('\n')
};
};
使用示例
# 运行审计并与本地基准比较,阈值设为 performance ≥ 90
lighthouse-ci -u https://example.com -b ./baseline.json -t '{"performance":90}'
可能的输出
⚠️ 检测到回归!
performance 分数 85 < 90
performance 分数下降: 92 → 85
如果所有指标都满足阈值:
✅ 没有发现回归。
将 CLI 集成到 CI
在 GitHub Actions 中,只需要添加一步:
- name: Run Lighthouse CI
run: npx lighthouse-ci -u ${{ secrets.SITE_URL }} -b ./baseline.json -t '{"performance":90}'
当审计失败时,process.exit(1) 会导致工作流标记为 failed,从而阻止代码合并。
结论
- 自动化:把性能回归检测嵌入到每次部署的流水线中,避免手动检查。
- 可定制:阈值和基准文件均可根据项目需求灵活配置。
- 即时反馈:开发者在 PR 阶段即可看到具体的回归信息,修复成本大幅降低。
如果你也在担心页面性能的意外下降,欢迎尝试这个 CLI 并根据自己的需求进行扩展。祝编码愉快!
Source: …
介绍
Google Lighthouse 非常适合一次性审计。但如果你在星期二修复了 LCP,星期五又发布了一个捆绑回归,没人会注意到,直到 Search Console 在三周后给你发邮件。
Lighthouse 告诉你网站今天有多快。kanmi 告诉你何时变慢。
npm install -g @knfrmd/kanmi
kanmi audit https://your-site.com
Kanmi Performance Audit
https://your-site.com
mobile · Slow 4G, 4x CPU · LH 12.0.0 · 14.2s
─────────────────────────────────────────────
Performance 72
Accessibility 95
Best Practices 100
SEO 91
Lab Metrics
─────────────────────────────────────────────
LCP 4,200ms NEEDS IMPROVEMENT
TBT 380ms NEEDS IMPROVEMENT
CLS 0.003 GOOD
FCP 1,800ms GOOD
Top Issues
─────────────────────────────────────────────
* Reduce unused JavaScript (~1.2s savings)
* Eliminate render‑blocking resources (~800ms savings)
一个命令。得分、实验室指标、主要问题。
功能说明
kanmi audit <url>– 运行 Lighthouse 并打印结果。kanmi monitor <url>– 运行 3 次审计(取中位数),保存到本地历史,检测回归。kanmi ci– 在 GitHub Actions 中强制阈值,失败时退出 1。
为什么不使用 Lighthouse CI?
Lighthouse CI 功能强大,但它假设:
- 一个服务器(LHCI 服务器或临时存储)
- 一个
.lighthouserc.js项目配置文件 - 在本地看到任何价值之前,需要进行 CI‑specific 的设置
kanmi 只需一条命令即可工作。无需服务器。无需数据库。只在 ~/.kanmi/history/ 中保存 JSON 文件,并自动与您自己的基准进行比较。
关于 WebPageTest、Calibre、SpeedCurve?
优秀的持续监控和真实用户仪表盘工具,但它们是需要账户、计费以及长期数据存储的托管服务。
kanmi 旨在满足不同的工作流:“这次部署是否导致性能下降?” —— 在本地一分钟内即可得到答案,无需账户。
| 工具 | 用途 |
|---|---|
| Lighthouse | 一次性审计 |
| Lighthouse CI | 带服务器的 CI 流水线 |
| WebPageTest / Calibre / SpeedCurve | 托管监控 + RUM |
| kanmi | 本地回归检测 |
监控捕捉审计遗漏的内容
kanmi monitor https://shop.example.com
Kanmi Monitor
Run #8 | 2026-02-28 | 3 runs (median)
─────────────────────────────────────────────
Performance 92 unchanged
Regressions
CRIT LCP: 2,100ms -> 2,600ms (+500ms)
Regression Policy
─────────────────────────────────────────────
Baseline median of last 5 runs
Rule flag if delta >= max(abs, baseline × rel%)
Fail exit 1 on critical/high severity
回归检测使用双阈值——绝对阈值 and 相对阈值。LCP 在 +150 ms or +10 % 时触发警报,以数值更大的为准。这可以防止在慢速站点上出现误报(150 ms 只是噪声),同时在快速站点上捕捉到小幅回归(10 % 更重要)。在拥有 5 次基线运行之前,系统不会评估回归,从而避免因数据不足而产生的误报。
CI 检查
kanmi ci --urls https://example.com --performance 90
如果阈值未达标或检测到关键回归,则退出码为 1。添加 --post-comment 可在 PR 中添加注释。
工程笔记
分数尺度约定
Lighthouse 分数在内部是 0‑1。许多包装器会转换为 0‑100 并引入错误。kanmi 在所有地方都保持 0‑1 数据——JSON 输出、存储、历史记录。0‑100 的转换仅在终端显示层进行,由 JSON schema 强制执行,CI 在每次推送时进行验证。
URL 规范化
如果你在周一监控 https://www.example.com/?utm_source=email,在周二监控 https://example.com/,它们需要映射到相同的基准。kanmi 在存储前会去除协议、www.、跟踪参数(共 14 项)、哈希片段和默认端口。已有 40 条单元测试覆盖此功能。
“陌生人模式” CI
CI 作业将 CLI 打包成 tarball,安装到空的 /tmp 目录中,并验证二进制文件能运行且 JSON 输出符合 schema。如果在全新安装时出现破坏,CI 会在 npm publish 之前捕获。
试一试
npm install -g @knfrmd/kanmi
kanmi audit https://your-site.com
kanmi monitor https://your-site.com
运行几次,你会看到回归检测自动启动。