性能优化最怕"感觉慢了"但没有依据。先把指标定义清楚,再按投入产出比从高到低逐项落地, 是效率最高的做法。这篇文章整理了一份我常用的清单,从"怎么量"到"怎么改"。
先看三个核心指标
- LCP(Largest Contentful Paint):首屏最大内容元素的渲染时间,衡量"页面看起来加载完了", 目标 < 2.5s;
- CLS(Cumulative Layout Shift):布局偏移累计分,衡量页面元素是否"跳动", 目标 < 0.1;
- INP(Interaction to Next Paint):交互响应延迟,衡量点击后界面多快给出反馈,目标 < 200ms。
这三个指标对应了用户体验的三个方面:加载快不快、稳不稳、跟不跟手。 用 Lighthouse 或 Chrome DevTools 的 Performance 面板可以很方便地测量。
图片:首屏优化的最大杠杆
图片往往占据页面传输体积的大头,优先级最高:
- 格式升级:用 WebP / AVIF 替代 JPEG / PNG,同等画质体积可减小 30%–70%;
- 尺寸匹配:不要用 2000px 的图展示 400px 的缩略图,按实际展示尺寸输出;
- 懒加载:视口外的图片加
loading="lazy",首屏只加载真正可见的; - 预留空间:给图片容器设置宽高比(aspect-ratio),避免加载后把页面"顶开",这是 CLS 的常见来源。
<img src="hero.webp"
width="1200" height="675"
fetchpriority="high"
alt="首屏大图">
<img src="thumb.webp"
width="400" height="300"
loading="lazy"
decoding="async"
alt="懒加载缩略图">
字体:别让文字"隐形"
自定义字体加载期间,浏览器可能不渲染文字(FOIT,Flash of Invisible Text), 直接拉高 LCP。优化手段:
- 用
font-display: swap,先显示系统字体,字体就绪后再切换; - 用
unicode-range做字体子集化,中文站只加载用到的字符; - 用
preload提前加载关键字体文件。
脚本与 CSS:减少主线程占用
-
脚本加
defer:不阻塞 HTML 解析,在 DOM 就绪后按顺序执行;async只适合完全独立的脚本(如统计代码); - 代码分割:路由级懒加载,首屏只下载当前页面需要的 JS 块(Code Splitting);
-
关键 CSS 内联:首屏样式直接内联在
<head>,外部样式表用media或异步加载,避免阻塞渲染; - preconnect 与 dns-prefetch:提前建立与第三方域名(CDN、字体站)的连接:
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
<link rel="dns-prefetch" href="https://api.example.com">
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
一个容易忽略的点:服务器响应时间
前端优化做得再好,TTFB(首字节时间)超过 1s 也无济于事。检查: 静态资源是否走了 CDN、是否有缓存(配合上篇的缓存策略)、服务端有没有慢查询或未压缩 (确保开启 gzip / brotli)。
落地顺序建议
- 先测一遍 Lighthouse,记下三个指标的基线值;
- 图片格式 + 尺寸 + 懒加载(收益最大,改动最小);
- 字体 swap + 子集化;
- 脚本 defer + 代码分割;
- CDN + 缓存 + 压缩(如果还没有);
- 再测一遍,对比基线,把数值写进文档,防止回退。
总结:先量化,再动手。图片是杠杆,字体别隐形,脚本别阻塞,服务器别拖后腿——按这个顺序做,首屏体验的提升是肉眼可见的。