Lighthouse CI 的 collect 阶段卡住或报错 ERR_CONNECTION_REFUSED,主因是 CI 中未启动待测服务;Lighthouse 不启动服务器,仅访问 http://localhost:8080,需手动启动服务、加 wait-on 等待、配置端口权限及沙箱参数。

为什么 lighthouse-ci 的 collect 阶段常卡住或报错 ERR_CONNECTION_REFUSED
本地跑通但 CI 中失败,大概率是没启动待测服务。Lighthouse 本身不启动服务器,只访问已有地址——它默认尝试连 http://localhost:8080,而多数 CI 环境里这个端口根本没服务在监听。
实操建议:
- 必须在
collect前显式启动服务,比如用npx http-server ./dist -p 8080或npm run serve -- --port=8080,并加&后台运行(注意不同 shell 对后台任务的处理差异) - 加等待逻辑,避免服务未就绪就发起检测:用
npx wait-on http://localhost:8080(需提前npm install -D wait-on) - 确认 CI 环境允许端口绑定(如 GitHub Actions 默认允许,GitLab CI 可能需设
services:或用 Docker) - 若用
chromium无头模式失败,可临时加--chromeFlags="--no-sandbox --disable-setuid-sandbox",但生产配置应优先修复权限而非绕过沙箱
如何配置 lhci collect 的阈值并在超限时让 CI 失败
阈值拦截不是靠 Lighthouse 报告生成后人工比对,而是由 lhci autorun 或手动调用 lhci upload + assert 实现。关键在 assert 阶段的规则定义。
实操建议:
- 在
.lighthouserc.json中写死断言规则,例如:{ "ci": { "collect": { "url": ["http://localhost:8080"] }, "assert": { "assertions": { "categories:performance": ["error", {"minScore": 0.8}], "metrics:first-contentful-paint": ["warn", {"maxNumericValue": 2000}], "accessibility": ["off"] } } } } -
lhci autorun会自动执行collect → upload → assert流程;若拆开执行,需确保upload成功后再跑lhci assert,否则找不到历史基线 - 注意
minScore是小数(0.8 表示 80 分),maxNumericValue单位是毫秒,且仅对具体指标(如first-contentful-paint)有效,不能对整个 category 用 numeric 断言 - CI 中建议加
--collect.numberOfRuns=1加速,但正式准入建议保留默认3次取中位数,避免单次抖动误判
如何让 lhci 在 PR 提交时只测变更页面,而不是全站扫描
Lighthouse CI 默认对配置里的 url 数组全量执行,不感知 Git 差异。所谓“只测变更页面”,需要外部逻辑提取改动文件、映射到路由,再动态构造 URL 列表。
实操建议:
- 用
git diff找出被修改的源码路径,再通过约定(如src/pages/foo.vue → /foo)映射为 URL,拼成数组传给lhci collect --url - 简单脚本示例(Bash):
URLS=(); for f in $(git diff --name-only origin/main...HEAD | grep -E '\.(vue|tsx?|jsx?)$'); do path=$(echo $f | sed -E 's|src/pages/(.*)\.(vue|tsx?)$|/\1|; s|/index$||'); URLS+=("http://localhost:8080$path"); done; npx lhci collect --url="${URLS[@]}" - 若项目路由非文件直出(如动态路由、SSR),需维护一份「变更文件→影响路由」的映射表,或退回到保守策略:只测核心路径(首页、关键转化页)+ 全量回归开关(如 nightly job)
- 注意:Lighthouse 不支持单页面内多个
url共享同一份报告,每个 URL 都是独立审计,所以 URL 数量直接影响 CI 耗时
上传报告后如何快速定位性能退化点,而不是只看红绿灯
lhci upload 会把报告推到 lhci server 或 lhci github-app,但默认只展示汇总分。退化往往藏在具体指标波动里,比如 total-blocking-time 上涨 300ms,但 performance category 分只跌了 2%。
实操建议:
- 启用
lhci server并配置collect.target="public",这样每次上传都会生成可比对的 HTML 报告链接,附带详细指标 delta 图表 - 在 CI 日志里直接打印关键指标变化:用
lhci upload --outputDir=./lh-report生成 JSON,再用jq提取对比字段,例如:jq '.runs[0].lhr.categories.performance.score, .runs[0].lhr.audits["total-blocking-time"].numericValue' ./lh-report/latest.json
- 若用 GitHub App,PR 评论里默认只显示 summary,需在
.lighthouserc.json中开启"githubAppToken"并设置"collect.uploadArtifacts": true,才能让详情链接出现在评论底部 - 警惕「伪稳定」:某些指标(如
speed-index)在低网速下波动极大,建议在 CI 中固定网络条件(--throttling.cpuSlowdownMultiplier=4)并禁用预加载(--chromeFlags="--disable-features=Translate")以提升可比性
阈值拦截真正难的不是写断言,而是确定哪个指标该设什么值——FCP 对静态页可以卡 1200ms,但对 SSR 页面可能得放宽到 2500ms;TBT 在弱网下容易虚高,却又是主线程阻塞的关键信号。这些得结合真实用户监控(RUM)数据反向校准,而不是照搬 Lighthouse 推荐值。










