Lighthouse 跑 60 分不可怕,可怕的是不知道每一分丢在哪里。这篇以一个真实企业官网从 61 分优化到 96 分的过程为线索,按扣分权重从大到小逐项给出修复手段与代码。
一、先看分数构成:优化优先级怎么排
| 维度 | 权重 | 常见瓶颈 |
|---|---|---|
| Performance | 55% | 未压缩图片、阻塞 JS、字体闪动 |
| Accessibility | 15% | 对比度不足、无 alt、表单无 label |
| Best Practices | 10% | 控制台报错、HTTP/1.1、过期 API |
| SEO | 10% | meta 缺失、低对比文本、无 crawlable link |
结论:性能一项占一半分数,先修性能,其他维度多数是"顺手修"。
二、LCP:最重的一块(往往占 3~5 秒)
1. 首屏大图三板斧
<Image
src="/banner.webp"
width={1920} height={640}
priority // ① 预加载 + 提升优先级
quality={82} // ② 质量调优,视觉无损
sizes="(max-width: 768px) 100vw, 1280px" // ③ 按视口下发合适尺寸
alt="企业形象"
/>
2. 字体导致的 LCP 拖延
自定义字体加载期间文字不渲染(FOIT)。修复:
@font-face {
font-family: 'BrandFont';
src: url('/fonts/brand.woff2') format('woff2');
font-display: swap; /* 先展示后备字体,加载完成再切换 */
size-adjust: 104%; /* 微调后备字体度量,减少切换抖动 */
}
中文字体体积巨大(一个字重 3~8MB),必须子集化:官网只保留品牌标语用到的两三百字,用 fontmin 或在线工具裁剪,体积可从 5MB 降到 80KB 以内。
3. 阻塞渲染的第三方脚本
统计、客服、地图脚本全部 defer 或动态加载;Next.js 中用 next/script 的 strategy="lazyOnload"。
三、CLS:页面跳动全清单
61 分的站点 CLS 常在 0.25 以上,逐项排查:
- 图片无宽高:所有
<img>必须带 width/height 或aspect-ratio,这是 CLS 第一大源 - 广告位/公告条动态插入:顶部公告条加载后把页面推下去。给容器预留
min-height,或用 skeleton 占位 - 字体切换抖动:见上文
size-adjust - 异步内容撑开容器:新闻列表加载前渲染 3 条灰色骨架卡片,高度锁定
- 动画使用 transform:位移动画用
transform而不是top/left,不触发重排
四、JS 体积与执行:TBT 的来源
1. 包分析先行
npx @next/bundle-analyzer # 或 vite-bundle-visualizer
典型发现:moment.js 带全部 locale 约 300KB → 换 dayjs 2KB;lodash 整包引入 → 按需 lodash-es 单函数导入;ECharts 整包 → 按图表类型注册:
import * as echarts from 'echarts/core';
import { BarChart } from 'echarts/charts';
import { GridComponent } from 'echarts/components';
echarts.use([BarChart, GridComponent]); // 体积从 990KB 降到 ~300KB
2. 长任务拆分
超过 50ms 的任务会阻塞交互(INP 变差)。大列表用虚拟滚动;重计算放 requestIdleCallback 或 Web Worker。
五、Accessibility:15% 权重的快修清单
- 所有功能性图片补
alt,装饰性图片alt="" - 文字对比度 ≥ 4.5:1——灰色
#999配白底只有 2.8:1,降到#595959即达标 <button>不要用<div onClick>代替,键盘用户无法触达- 表单控件关联
<label for> html lang="zh-CN"别漏
六、优化前后数据对比(真实项目)
| 指标 | 优化前 | 优化后 | 关键动作 |
|---|---|---|---|
| Performance | 61 | 96 | 图片 WebP + priority、字体子集化 |
| LCP | 4.8s | 1.4s | 首屏图 389KB→68KB、预加载 |
| CLS | 0.31 | 0.02 | 全站图片定尺寸 + 骨架占位 |
| JS 传输体积 | 1.2MB | 386KB | 依赖替换 + 代码拆分 |
小结
性能优化八二开:80% 的收益来自图片、字体、依赖体积三件事,剩下 20% 才是精妙的代码技巧。先跑一次 Lighthouse 截图存档,按本文清单逐项执行,再跑一次对比——数据不会说谎。