Lighthouse 跑分:从 60 到 90 分,我掉了多少头发?
从 60 分到 90 分的 Lighthouse 跑分提升,是一场与性能、可访问性、SEO 和最佳实践的硬仗。过程中踩过的坑、熬过的夜、掉过的头发,最终化成了这些实战经验。
性能优化:从加载龟速到闪电响应
性能分数低,往往是资源加载和渲染阻塞的问题。一个典型的例子是未优化的图片和未压缩的 JavaScript。比如,一个电商网站的首页可能塞满了高清产品图:
<!-- 糟糕的写法 -->
<img src="product-huge.jpg" alt="产品图">
优化方案是使用现代图片格式和懒加载:
<!-- 优化后 -->
<img
src="product.webp"
srcset="product-small.webp 480w, product-medium.webp 1024w"
sizes="(max-width: 600px) 480px, 1024px"
loading="lazy"
alt="产品图"
>
JavaScript 的优化更关键。曾经遇到一个案例,第三方库占用了 70% 的打包体积:
// 原始代码:直接引入整个 lodash
import _ from 'lodash';
_.debounce(handler, 300);
// 优化后:按需引入
import debounce from 'lodash/debounce';
debounce(handler, 300);
可访问性:不只是给屏幕阅读器的恩赐
可访问性分数低往往源于忽略的 ARIA 属性和颜色对比度。一个常见错误是自定义按钮:
<!-- 问题代码 -->
<div class="btn" onclick="submit()">提交</div>
屏幕阅读器无法识别这是个按钮。修正方案:
<button class="btn" aria-label="提交订单">提交</button>
颜色对比度问题更隐蔽。某次发现设计师指定的主色调 #FF7E7E 与白色背景的对比度只有 3.2:1(WCAG 要求至少 4.5:1)。解决方案是用工具检查后调整:
/* 修改前 */
.button {
background-color: #FF7E7E;
color: white;
}
/* 修改后 */
.button {
background-color: #E74C3C; /* 对比度 5.92:1 */
color: white;
}
SEO:让爬虫看得懂你的心血
SEO 分数低通常因为缺失元数据和语义化标签。一个新闻网站可能这样写标题:
<!-- 糟糕的写法 -->
<div class="title">最新疫情通报</div>
优化后应该使用语义化标签并添加结构化数据:
<h1 itemscope itemtype="https://schema.org/NewsArticle">
<span itemprop="headline">最新疫情通报</span>
</h1>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "NewsArticle",
"headline": "最新疫情通报"
}
</script>
最佳实践:那些容易忽略的细节
最佳实践扣分点常常是安全策略和现代 API 的使用。例如没有 CSP 头会导致控制台警告:
# 原始响应头
Content-Security-Policy: default-src 'self'
更完善的策略应该这样:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' cdn.example.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
另一个高频问题是过时的 API。曾发现某页面使用 document.write
加载广告:
// 过时写法
document.write('<script src="ads.js"></script>');
// 现代替代方案
const script = document.createElement('script');
script.src = 'ads.js';
document.body.append(script);
调试工具:Chrome DevTools 的进阶用法
Lighthouse 的审计结果需要结合 DevTools 深入分析。网络面板可以识别未使用的 CSS:
/* 未使用的样式 */
.old-banner { display: none; }
性能面板能捕获布局抖动。通过录制发现某个动画导致持续重排:
// 问题代码:同步读取布局属性
function animate() {
element.style.left = element.offsetLeft + 1 + 'px';
requestAnimationFrame(animate);
}
// 修复:使用 transform 避免重排
function animate() {
element.style.transform = `translateX(${x++}px)`;
requestAnimationFrame(animate);
}
持续监控:把优化变成日常
一次优化远远不够,需要建立监控机制。通过 GitHub Actions 自动化 Lighthouse 检测:
# .github/workflows/lighthouse.yml
name: Lighthouse Audit
on: [push]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: treosh/lighthouse-ci-action@v8
with:
urls: |
https://example.com
https://example.com/pricing
budgetPath: ./lighthouse-budget.json
预算文件示例:
{
"performance": 90,
"accessibility": 95,
"seo": 90,
"best-practices": 90
}
那些让人头秃的疑难杂症
遇到过最棘手的问题是字体加载导致的布局偏移。某次优化后发现 CLS(布局偏移)分数反而下降:
/* 问题根源:备用字体尺寸差异 */
body {
font-family: 'CustomFont', Arial;
}
解决方案是定义字体尺寸匹配:
body {
font-family: 'CustomFont', Arial;
font-size: 16px;
line-height: 1.5;
}
/* 确保备用字体匹配 */
@supports not (font-family: 'CustomFont') {
body {
font-size: 15.5px;
letter-spacing: 0.2px;
}
}
另一个坑是 Service Worker 缓存策略。错误的配置导致用户永远看不到更新:
// 错误缓存策略
self.addEventListener('fetch', event => {
event.respondWith(caches.match(event.request));
});
// 正确做法:网络优先,失败回退缓存
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request)
.catch(() => caches.match(event.request))
);
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn