Lighthouse 跑 60 分不可怕,可怕的是不知道每一分丢在哪里。这篇以一个真实企业官网从 61 分优化到 96 分的过程为线索,按扣分权重从大到小逐项给出修复手段与代码。

一、先看分数构成:优化优先级怎么排

维度权重常见瓶颈
Performance55%未压缩图片、阻塞 JS、字体闪动
Accessibility15%对比度不足、无 alt、表单无 label
Best Practices10%控制台报错、HTTP/1.1、过期 API
SEO10%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" 别漏

六、优化前后数据对比(真实项目)

指标优化前优化后关键动作
Performance6196图片 WebP + priority、字体子集化
LCP4.8s1.4s首屏图 389KB→68KB、预加载
CLS0.310.02全站图片定尺寸 + 骨架占位
JS 传输体积1.2MB386KB依赖替换 + 代码拆分

小结

性能优化八二开:80% 的收益来自图片、字体、依赖体积三件事,剩下 20% 才是精妙的代码技巧。先跑一次 Lighthouse 截图存档,按本文清单逐项执行,再跑一次对比——数据不会说谎。