TL;DR: 达成 Lighthouse 95+ 不是在追逐一个数字——而是在构建一个直接影响 SaaS 转化率的高性能体验。本指南涵盖 Core Web Vitals 优化、流式 SSR、Critical CSS、代码分割、图片优化和缓存策略,每条建议均可落地并已在生产环境验证。文末附 30 条检查清单。
引言:为什么 Lighthouse 95+ 对 SaaS 如此重要
在 SaaS 领域,每毫秒都至关重要。Google 的研究反复证明,移动端页面加载延迟 1 秒,转化率下降高达 20%。对于一款月 ARPU 为 100 美元、月新增注册 1 万人的 B2B SaaS 产品,这一延迟意味着每年超过 200 万美元的收入损失。
但影响远不止于此:
- SEO 排名: Google 将 Core Web Vitals 作为排名信号。Lighthouse 得分低于 50 的网站难以获得有竞争力的排名。
- 用户信任: Lighthouse 得分与用户感知的可靠性高度相关。
- 广告投放效率: Google Ads 质量得分越低,每次点击成本越高。
Lighthouse 95+ 是一个复合增长杠杆,同时作用于获客、激活和留存。
理解 Core Web Vitals
| 指标 | 衡量内容 | 目标值 |
|---|---|---|
| LCP (Largest Contentful Paint) | 加载性能 | <= 2.5s |
| CLS (Cumulative Layout Shift) | 视觉稳定性 | <= 0.1 |
| INP (Interaction to Next Paint) | 交互响应 | <= 200ms |
性能预算:从第一天起设定目标
为以下指标定义预算:
- JavaScript 打包体积: 关键路由 150 KB(压缩后),上限 300 KB
- 可交互时间: 3G 网络下 < 3s
- LCP: < 2.0s
- 单页总重量: < 500 KB(压缩后)
在 CI 中强制执行:
// lighthouse-budget.js
module.exports = {
ci: {
collect: { numberOfRuns: 3, settings: { preset: 'desktop' } },
assert: {
assertions: {
'categories:performance': ['error', { minScore: 0.95 }],
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
'total-blocking-time': ['error', { maxNumericValue: 200 }],
},
},
},
};
LCP 优化
1. 流式 SSR
流式 SSR 将 HTML 逐步推送给浏览器,通过立即渲染首屏内容显著改善 LCP。关于流式 SSR 的底层原理,可参阅我们的流式 SSR 深度解析。TanStack Start 开箱即支持流式 SSR:
const router = createRouter({
routeTree,
defaultPreload: 'intent',
// Streaming is enabled by default in TanStack Start
});
部署在 Cloudflare Workers 上时,流式 SSR 利用边缘基础设施将 TTFB 降至最低,并从距离用户最近的节点交付 HTML,进一步放大了服务端渲染的性能优势。
2. Critical CSS
将首屏内容所需的 CSS 内联,其余延迟加载:
<head>
<style>
/* Critical CSS — inline above-the-fold styles */
header, .hero, .cta-button { /* essential styles */ }
</style>
<link rel="preload" href="/styles/full.css" as="style"
onload="this.onload=null;this.rel='stylesheet'" />
<noscript><link rel="stylesheet" href="/styles/full.css" /></noscript>
</head>
3. 字体加载
使用 font-display: swap 并预加载主字体:
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-display: swap;
font-weight: 100 900;
}
在 HTML head 中预加载:
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin />
4. 优化 LCP 元素
- 预加载:
<link rel="preload" as="image" href="/hero.webp" /> - 使用响应式图片适配不同视口
- 不要对 LCP 元素使用懒加载
CLS 优化
1. 设置明确尺寸
<img
src="/dashboard-screenshot.webp"
width="1200"
height="675"
alt="Dashboard preview"
loading="lazy"
/>
2. 字体后备指标
@font-face {
font-family: 'Inter Fallback';
src: local('Arial');
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}
3. 为动态内容预留空间
.newsletter-signup-placeholder {
min-height: 120px;
/* Reserve space while async content loads */
}
JavaScript 优化
1. 基于路由的代码分割
TanStack Router 原生支持基于路由的代码分割:
// routes/dashboard.tsx
export const Route = createLazyRoute('/dashboard')({
component: DashboardComponent,
});
2. Tree Shaking
- 使用命名导入:
import { useQuery } from '@tanstack/react-query' - 标记无副作用的包:
"sideEffects": false
3. 懒加载非关键代码
<script>
window.addEventListener('load', () => {
setTimeout(() => {
const script = document.createElement('script');
script.src = 'https://widget.example.com/loader.js';
script.async = true;
document.body.appendChild(script);
}, 3000);
});
</script>
图片优化
1. 使用 srcset 的响应式图片
<img
src="/hero-1200.webp"
srcset="/hero-400.webp 400w, /hero-800.webp 800w, /hero-1200.webp 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
width="1200" height="675" alt="Product dashboard"
/>
2. 现代格式:WebP 和 AVIF
<picture>
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img src="/hero.jpg" width="1200" height="675" alt="Hero" />
</picture>
缓存策略
1. CDN 缓存
Cache-Control: public, max-age=31536000, immutable # Versioned assets
Cache-Control: public, max-age=3600, s-maxage=86400 # HTML pages
2. TanStack Query 缓存
const { data } = useQuery({
queryKey: ['pricing-plans'],
queryFn: fetchPricingPlans,
staleTime: 5 * 60 * 1000,
gcTime: 30 * 60 * 1000,
});
30 条性能检查清单
关键项
- 已识别并预加载 LCP 元素
- 所有图片均设置了明确宽高
- Critical CSS 已内联,完整 CSS 延迟加载
- 自定义字体使用
font-display: swap - 无阻塞渲染的第三方脚本
- LCP 图片使用 WebP/AVIF + 响应式 srcset
- 服务器响应时间(TTFB)< 800ms
- 已实现基于路由的代码分割
- 已移除或延迟加载未使用的 JavaScript
- 首屏大图未使用懒加载
高优先级
- 所有光栅图片已转换为 WebP 或 AVIF
- 已调优字体后备指标
- 第三方嵌入元素已预留空间
- 分析类脚本在 onLoad 后加载
- 已识别并拆分耗时任务(>50ms)
- JavaScript 打包使用 Brotli 压缩
- 静态资源使用 immutable 缓存头
- CDN 已为所有资源类型配置
- TanStack Query staleTime 设置合理
- Service Worker 缓存 API 响应
中优先级
- 所有图片使用懒加载(LCP 元素除外)
- 关键域名添加 preconnect 提示
- 分析类域名添加 dns-prefetch
- HTML 已压缩
- CSS 已压缩并清除未使用规则
- 首屏无阻塞渲染的 JS
- 关键 API 路由已预加载
- 谨慎使用 will-change
- 每次页面加载的 301 重定向最小化
- 在每个 PR 中运行 Lighthouse CI
结语
Lighthouse 95+ 的意义在于构建一个快速、可靠、令人愉悦的用户体验,从而直接推动 SaaS 业务增长。方法论是系统化的:
- 写代码前先设定预算
- 在实验室和真实环境中持续测量
- 优化关键路径: 流式 SSR、Critical CSS、字体加载、图片
- 控制 JavaScript: 路由分割 + 延迟加载
- 激进缓存所有内容
从检查清单开始,先抓关键项。在每个 PR 中运行 Lighthouse CI。你的用户——和你的收入——都会为此感谢你。完整的优化型 SaaS 应用部署实战演示,请参阅 TanStack Start 部署指南。