17.2 Lighthouse CI + 自定义断言
在现代全栈开发流程中,性能与SEO不再是“上线后”才考虑的问题。Lighthouse CI 将 Lighthouse 审计集成到持续集成(CI)管道中,允许开发者在每次代码合并前自动检测性能、可访问性、SEO 和最佳实践等指标。结合自定义断言,我们可以将 SEO 与 GEO 的硬性要求转化为自动化测试用例,确保每一次部署都不会破坏已有的优化成果。
17.2.1 Lighthouse CI 的核心价值
Lighthouse CI 解决了传统性能审计的痛点:
- 手动审计不可重复:本地运行 Lighthouse 结果受环境、网络影响,无法作为团队统一标准。
- 回归风险不可控:一次看似无害的 CSS 或 JavaScript 改动,可能导致 LCP 飙升或 Schema 被破坏。
- 缺乏历史对比:无法追踪性能指标随时间的变化趋势。
通过 Lighthouse CI,你可以:
- 在 Pull Request 中自动生成性能报告,并与基线(如生产环境或上次提交)对比。
- 设置硬性阈值,当关键指标(如 LCP、CLS、SEO 得分)低于标准时,阻止合并。
- 将审计结果集成到 GitHub Checks、GitLab CI 等系统中,形成开发流程的一环。
17.2.2 基础配置与集成
1. 安装与初始化
npm install -g @lhci/cli
在项目根目录创建 lighthouserc.js 配置文件:
module.exports = {
ci: {
collect: {
// 要审计的页面URL列表
url: [
'http://localhost:3000/',
'http://localhost:3000/products',
'http://localhost:3000/faq',
],
// 启动本地服务器的方式
startServerCommand: 'npm run start',
// 收集次数,取中位数结果
numberOfRuns: 3,
},
upload: {
// 上传到临时存储(可选)
target: 'temporary-public-storage',
},
assert: {
// 断言配置(见下文)
assertions: {
// 预设的 Lighthouse 审计规则
'categories:performance': ['warn', { minScore: 0.9 }],
'categories:seo': ['error', { minScore: 0.95 }],
},
},
},
};
2. CI 集成示例(GitHub Actions)
在 .github/workflows/lighthouse.yml 中:
name: Lighthouse CI
on: [pull_request]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npm run build
- name: Run Lighthouse CI
run: |
npm install -g @lhci/cli
lhci autorun
当 PR 提交后,Lighthouse CI 会自动运行,并在 PR 的 Checks 中显示结果。如果 seo 类别得分低于 0.95,CI 将失败,阻止合并。
17.2.3 自定义断言:从通用指标到业务级规则
Lighthouse 内置了丰富的审计项,但对于 SEO/GEO 工程师来说,我们往往需要更细粒度的自定义断言。例如:
- 确保结构化数据(JSON-LD)存在且有效:即使 SEO 得分高,也可能因为 Schema 缺失或错误而影响生成引擎引用。
- 确保关键页面包含特定元素:如 FAQ 页面必须包含
QAPage标记。 - 确保页面加载时间满足特定阈值:针对不同用户群体(如移动端)设置更严格的 LCP 标准。
1. 使用 Lighthouse 内置审计项
Lighthouse 的审计项以 audits 对象形式暴露。例如:
assertions: {
// 确保所有图片都有alt属性
'image-alt': ['error'],
// 确保页面有正确的文档标题
'document-title': ['error'],
// 确保robots meta标签正确
'meta-robots': ['error'],
}
2. 自定义断言:基于 Lighthouse 结果
Lighthouse CI 允许你通过 assertions 中的自定义函数实现复杂逻辑。例如,检查 JSON-LD 是否存在:
assertions: {
// 自定义断言:检查页面是否包含有效的JSON-LD
'custom-jsonld': ['error', {
// 使用 Lighthouse 的 result 对象
run: (result) => {
const jsonldScripts = result.lhr.audits['json-ld']?.details?.items;
if (!jsonldScripts || jsonldScripts.length === 0) {
throw new Error('页面缺少 JSON-LD 结构化数据');
}
// 可以进一步验证内容
return true;
},
}],
}
3. 使用 Puppeteer 扩展自定义审计
对于更复杂的场景(如验证动态渲染的 Schema 是否正确),可以编写自定义 Puppeteer 脚本,并将其作为 Lighthouse 的额外收集步骤。
示例:在 Lighthouse 收集前,注入一段脚本检查 __NEXT_DATA__ 中的结构化数据:
// custom-collect.js
const puppeteer = require('puppeteer');
module.exports = async (url) => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle0' });
// 检查 Next.js 的 __NEXT_DATA__ 中是否包含预期的 Schema
const schemaData = await page.evaluate(() => {
const script = document.getElementById('__NEXT_DATA__');
if (!script) return null;
return JSON.parse(script.textContent);
});
if (schemaData?.props?.pageProps?.schema) {
console.log('Schema found:', schemaData.props.pageProps.schema['@type']);
} else {
throw new Error('Expected Schema not found in __NEXT_DATA__');
}
await browser.close();
};
然后在 lighthouserc.js 中引用:
collect: {
// ...
puppeteerScript: 'custom-collect.js',
}
17.2.4 针对 GEO 的断言实践
生成式引擎(如 Perplexity、Bing Chat)对页面的要求与传统 SEO 略有不同。以下是一些针对 GEO 的自定义断言建议:
1. 检查 Speakable 标记
assertions: {
'custom-speakable': ['warn', {
run: (result) => {
const items = result.lhr.audits['json-ld']?.details?.items;
if (!items) return true; // 不强制,但警告
const hasSpeakable = items.some(item =>
item?.jsonld?.speakable?.type === 'SpeakableSpecification'
);
if (!hasSpeakable) {
console.warn('页面未包含 Speakable 结构化数据,可能影响语音搜索');
}
return true;
},
}],
}
2. 验证 FAQ 页面结构
assertions: {
'custom-faq-structure': ['error', {
run: (result) => {
const items = result.lhr.audits['json-ld']?.details?.items;
if (!items) throw new Error('FAQ 页面必须包含 JSON-LD');
const faqItem = items.find(item =>
item?.jsonld?.['@type'] === 'FAQPage'
);
if (!faqItem) throw new Error('FAQ 页面缺少 FAQPage 标记');
const questions = faqItem.jsonld.mainEntity;
if (!questions || questions.length < 3) {
throw new Error('FAQ 页面至少包含 3 个问答对');
}
return true;
},
}],
}
3. 监控生成引擎引用指标(外部集成)
Lighthouse CI 本身不直接测量生成引擎引用,但你可以通过自定义断言调用外部 API 来检查。例如,在断言中调用 Perplexity API 检查当前页面是否被引用:
assertions: {
'custom-perplexity-reference': ['warn', {
run: async (result) => {
const pageUrl = result.lhr.finalUrl;
const response = await fetch('https://api.perplexity.ai/search', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: JSON.stringify({ query: `site:${new URL(pageUrl).hostname}` }),
});
const data = await response.json();
const isReferenced = data.results.some(r => r.url === pageUrl);
if (!isReferenced) {
console.warn(`页面 ${pageUrl} 未在 Perplexity 中被引用`);
}
return true;
},
}],
}
注意:外部 API 调用会增加 CI 运行时间,建议仅在关键页面(如首页、核心产品页)启用,或作为定期巡检而非每次 PR 检查。
17.2.5 常见问题与最佳实践
1. 测试环境一致性
- 使用 Docker 或无头浏览器:确保 CI 环境与本地环境一致,避免因系统字体、GPU 等差异导致分数波动。
- 固定网络条件:使用 Lighthouse 的
--throttling参数模拟 3G 或 4G 网络,获得可重复的结果。
2. 阈值设置策略
- 渐进式收紧:初期设置宽松阈值(如 SEO 得分 > 0.8),避免频繁失败打击团队信心。随着优化深入,逐步提升至 0.95 以上。
- 区分页面类型:首页和核心转化页设置严格阈值,而博客文章或帮助页面可适当放宽。
3. 与 SEO/GEO 监控系统联动
Lighthouse CI 的结果可以自动推送到你的监控仪表盘(如 Prometheus、Grafana)。例如,在 CI 脚本中解析 Lighthouse 报告,提取关键指标并写入时序数据库:
# 解析 Lighthouse 报告并推送指标
lhci collect --url=http://localhost:3000 --numberOfRuns=1
lhci upload --target=filesystem --outputDir=./lhci-reports
# 使用 jq 提取 LCP 并推送
LCP=$(jq '.categories.performance.auditRefs[] | select(.id=="largest-contentful-paint") | .result.numericValue' ./lhci-reports/manifest.json)
curl -X POST "http://prometheus-pushgateway:9091/metrics/job/lighthouse/instance/$CI_COMMIT_SHA" \
--data-binary "lighthouse_lcp_seconds $LCP"
4. 调试失败断言
当自定义断言失败时,Lighthouse CI 会输出详细的错误信息。在本地调试时,可以使用 lhci collect 命令生成报告,然后手动运行断言逻辑:
lhci collect --url=http://localhost:3000
lhci assert --config=./lighthouserc.js
17.2.6 总结
Lighthouse CI + 自定义断言将 SEO/GEO 优化从“人工检查”升级为“自动化防线”。通过将 Core Web Vitals、结构化数据、生成引擎引用等关键指标转化为可执行的测试用例,全栈工程师可以:
- 在代码层面:确保每次提交都不引入性能或 SEO 回归。
- 在流程层面:将优化标准嵌入开发文化,而非事后补救。
- 在结果层面:持续维护页面在传统搜索和生成式引擎中的健康度。
下一步,你可以将 Lighthouse CI 与第 17.1 节的 PR 阶段检测(Schema 破坏、robots.txt 变更)结合,构建完整的 SEO/GEO 自动化质检流水线。
