前端首屏加载慢应该如何优化?
简化版
首屏慢要先按链路定位:HTML 是否返回晚、关键资源是否发现晚或下载慢、主线程是否被 JS 阻塞、关键内容是否等客户端数据。再分别优化 TTFB、关键 CSS/JS、LCP 资源、代码拆分和渲染方式,并用真实用户的 LCP、INP、CLS 与实验室瀑布验证,骨架屏只能改善等待感,不能替代根因优化。
详细版
排查先确认“慢”的表现:白屏对应 FCP,主内容晚对应 LCP,看得到但点不动要看 INP 和长任务。Network 用于分析 HTML、资源优先级和依赖瀑布,Performance 用于看解析、执行、布局和绘制。
优化顺序通常是缩短 TTFB,让浏览器尽早发现 LCP 图片、字体和关键 CSS;减少首屏 JS 下载与执行,延后非首屏路由和重组件;按场景采用 SSG、SSR 或流式渲染,避免主内容必须等完整客户端启动才出现。
性能目标应以页面类型和用户分群制定。当前 Core Web Vitals 的良好阈值是 P75 LCP 不超过 2.5 秒、INP 不超过 200 毫秒、CLS 不超过 0.1,但项目还应定义首屏 JS、图片和关键请求链预算。
完整版教学
一、先把“首屏”变成可测量的问题
首屏不是统一的浏览器事件。用户可能抱怨空白、主图晚、文字跳动或按钮无响应,这些现象分别落在加载、视觉稳定和交互响应上。
| 现象 | 主要指标 | 优先检查 |
|---|---|---|
| 很久没有内容 | TTFB、FCP | HTML、阻塞 CSS |
| 主内容出现晚 | LCP | LCP 资源与渲染延迟 |
| 页面不断跳动 | CLS | 图片尺寸、动态插入 |
| 看得到但点不动 | INP、Long Task | 主线程 JS |
心法:先指出“哪一段慢”,再选择手段;没有瓶颈证据的优化清单只是猜测。
二、关键渲染路径怎样决定首次显示
浏览器先请求 HTML,解析时发现 CSS、脚本、图片和字体。CSSOM 与 DOM 参与渲染树,样式、布局、绘制完成后用户才看到像素;同步阻塞脚本还可能暂停 HTML 解析。
导航 → DNS/连接/TLS → HTML(TTFB)
↓解析
CSS ──> CSSOM ─┐
DOM ───────────┼→ layout → paint
JS ─解析/执行───┘
关键路径优化不是删除所有资源,而是让当前视口必需资源更早发现、更短、更少阻塞。非关键代码和样式延后时还要防止闪烁、布局变化与交互缺失。
三、网络与服务端为什么常是第一段瓶颈
HTML 没回来前,浏览器通常无法从正文发现后续资源。TTFB 包含重定向、连接、服务端排队与处理、到首字节传输,不应机械归因于后端某一个函数。
假设 TTFB 从 1.2 秒降到 0.35 秒,后续关键链都可理论上提前约 0.85 秒开始。可用 CDN HTML 缓存、边缘渲染、数据库与接口优化、连接复用降低时间,但个性化页面必须设计正确缓存键和失效策略。
第三方域名过多也会重复支付 DNS、连接和 TLS 成本。合并来源不是绝对目标,应根据缓存、隔离和 CDN 能力判断,不能为了少一个域名破坏长期缓存或安全边界。
四、资源发现顺序比单纯压缩更容易被忽略
LCP 背景图若藏在晚到的 CSS 中,或图片 URL 必须等客户端 JS 请求数据后才生成,即使文件只有 80 KB,也可能因为发现晚而拖慢。关键图片最好能从初始 HTML 直接发现,并避免 loading="lazy"。
<img
src="/hero-960.avif"
width="960"
height="540"
fetchpriority="high"
alt="产品主视觉"
/>
fetchpriority="high" 是优先级提示,不会替代资源早发现,也不能给十张图同时使用。preload 同样只应给少数确实关键且会被页面消费的资源,否则会争抢带宽或产生未使用警告。
五、JS 成本包含下载之外的主线程工作
压缩后的 250 KB JS 下载完成后仍需解压、解析、编译、执行并挂载事件。在低端手机上,同一 bundle 的执行时间可能是开发机的数倍,所以只报 transfer size 不足以证明首屏快。
首屏保留路由壳、当前页面和必要交互,编辑器、图表、后台模块用动态导入延后。若原首屏 JS 为 600 KB,拆出 360 KB 非关键代码,初始体积下降 60%;还要确认剩余代码执行时间及懒加载后的交互等待。
长任务要按用户路径拆分或移出主线程。把一个函数拆成五个同步函数不会让出执行权,必须在任务边界 yield,或把不接触 DOM 的重计算交给 Worker。
六、SSR、SSG、CSR 与骨架屏各自解决什么
SSG 在构建期生成 HTML,适合稳定内容;SSR 请求时生成,适合动态与个性化内容;CSR 依赖客户端生成,首屏可能等待 JS 和接口。SSR/SSG 能让内容早到,但仍需控制服务端耗时、水合 JS 和缓存。
| 方案 | 首屏优势 | 主要代价 |
|---|---|---|
| SSG | HTML 可缓存、响应快 | 内容更新需重建或增量策略 |
| SSR | 动态内容直接入 HTML | 服务端成本、TTFB 与水合 |
| CSR | 架构简单、客户端交互统一 | 内容发现和渲染链可能更晚 |
骨架屏是在内容未就绪时给视觉反馈,它不减少字节、计算或接口时间。骨架尺寸若和真实内容不同,还可能引入 CLS;它应是状态设计,而不是性能成绩本身。
七、常见误区与追问
- 误区:首屏慢就先上 SSR。 若根因是慢接口、超大图片或水合长任务,SSR 可能只移动成本,必须先定位。
- 误区:骨架屏能提高实际加载速度。 它改善等待感,但不会直接缩短关键资源和主线程耗时。
- 误区:资源全部 preload 会更快。 过多高优先级请求会竞争带宽,真正关键资源可能变慢。
- 追问:为什么 HTML 很快返回,LCP 仍然很差? LCP 资源可能发现晚、下载慢,或主线程与 CSS 让元素渲染延迟。
- 追问:首屏 JS 体积降了为何仍卡? 代码初始化、框架水合和第三方脚本执行时间可能仍然很长。
- 追问:怎样设性能预算? 按页面类型约束关键资源体积、请求链、主线程时间和现场 P75 指标,并在 CI/RUM 检查。
- 追问:实验室 Lighthouse 很好,线上为什么差? 实验室是固定环境,真实用户设备、网络、缓存状态和交互路径更复杂。
八、加强记忆
用“定现象、拆链路、早发现、少执行、验现场”排查首屏:先用 FCP/LCP/INP/CLS 描述问题,再沿 HTML、关键资源和主线程找最长环节;让 LCP 内容从初始文档可发现,只让首屏为必要代码付费;最后以真实用户分位数验证,SSR 与骨架屏都必须回到具体瓶颈判断。