Web 性能优化实战指南
为什么性能很重要?
研究表明:
- 页面加载时间每增加 1 秒,转化率下降 7%
- 53% 的用户会放弃加载超过 3 秒的页面
- Google 将页面速度作为 SEO 排名因素
性能指标
Core Web Vitals
Google 定义的三个核心指标:
-
LCP (Largest Contentful Paint): 最大内容绘制
- 目标: < 2.5s
- 衡量加载性能
-
FID (First Input Delay): 首次输入延迟
- 目标: < 100ms
- 衡量交互性
-
CLS (Cumulative Layout Shift): 累积布局偏移
- 目标: < 0.1
- 衡量视觉稳定性
优化策略
1. 资源优化
图片优化
<!-- 使用现代图片格式 -->
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Description" loading="lazy">
</picture>
<!-- 响应式图片 -->
<img
srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
src="medium.jpg"
alt="Responsive image"
>
JavaScript 优化
// 代码分割
const HeavyComponent = lazy(() => import('./HeavyComponent'));
// 动态导入
button.addEventListener('click', async () => {
const module = await import('./analytics.js');
module.trackEvent('button-click');
});
// Tree shaking - 只导入需要的部分
import { debounce } from 'lodash-es'; // ✅
// import _ from 'lodash'; // ❌ 导入整个库
CSS 优化
/* 关键 CSS 内联 */
<style>
/* 首屏必需的样式 */
.hero { background: #000; color: #fff; }
</style>
/* 非关键 CSS 异步加载 */
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
2. 网络优化
使用 CDN
<!-- Cloudflare CDN 示例 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
HTTP/2 和 HTTP/3
- 多路复用
- 服务器推送
- 头部压缩
缓存策略
// Service Worker 缓存
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
# Nginx 缓存配置
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
3. 渲染优化
虚拟滚动
// React 虚拟列表示例
import { FixedSizeList } from 'react-window';
function VirtualList({ items }) {
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={50}
width="100%"
>
{({ index, style }) => (
<div style={style}>{items[index]}</div>
)}
</FixedSizeList>
);
}
防抖和节流
// 防抖 - 等待用户停止输入
const debounce = (fn, delay) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
};
// 节流 - 限制执行频率
const throttle = (fn, limit) => {
let inThrottle;
return (...args) => {
if (!inThrottle) {
fn(...args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
};
// 使用示例
const handleScroll = throttle(() => {
console.log('Scrolling...');
}, 200);
const handleSearch = debounce((query) => {
searchAPI(query);
}, 300);
避免布局抖动
// ❌ 强制同步布局
for (let i = 0; i < elements.length; i++) {
const height = elements[i].offsetHeight; // 读
elements[i].style.height = height + 10 + 'px'; // 写
}
// ✅ 批量读写
const heights = elements.map(el => el.offsetHeight); // 批量读
elements.forEach((el, i) => {
el.style.height = heights[i] + 10 + 'px'; // 批量写
});
4. 预加载策略
<!-- DNS 预解析 -->
<link rel="dns-prefetch" href="https://api.example.com">
<!-- 预连接 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<!-- 预加载关键资源 -->
<link rel="preload" href="main.js" as="script">
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
<!-- 预获取下一页资源 -->
<link rel="prefetch" href="/next-page.html">
5. 字体优化
@font-face {
font-family: 'CustomFont';
src: url('font.woff2') format('woff2');
font-display: swap; /* 避免不可见文本 */
}
/* 子集化字体 */
@font-face {
font-family: 'CustomFont';
src: url('font-latin.woff2') format('woff2');
unicode-range: U+0000-00FF; /* 只包含拉丁字符 */
}
监控和测试
性能测试工具
- Lighthouse: Chrome DevTools 集成
- WebPageTest: 详细的瀑布图分析
- Chrome DevTools Performance: 运行时性能分析
持续监控
// Web Vitals 监控
import { getCLS, getFID, getLCP } from 'web-vitals';
function sendToAnalytics(metric) {
fetch('/analytics', {
method: 'POST',
body: JSON.stringify(metric),
});
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);
Real User Monitoring (RUM)
// 使用 Performance API
window.addEventListener('load', () => {
const perfData = performance.getEntriesByType('navigation')[0];
console.log('DNS 查询:', perfData.domainLookupEnd - perfData.domainLookupStart);
console.log('TCP 连接:', perfData.connectEnd - perfData.connectStart);
console.log('请求响应:', perfData.responseEnd - perfData.requestStart);
console.log('DOM 解析:', perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart);
});
优化检查清单
- 启用 gzip/brotli 压缩
- 图片懒加载
- 代码分割和按需加载
- 使用 CDN
- 设置合理的缓存策略
- 优化关键渲染路径
- 减少第三方脚本
- 使用 HTTP/2 或 HTTP/3
- 实现 Service Worker
- 监控 Core Web Vitals
实际案例
我最近优化了一个电商网站:
优化前:
- LCP: 4.2s
- FID: 180ms
- CLS: 0.25
优化后:
- LCP: 1.8s (-57%)
- FID: 45ms (-75%)
- CLS: 0.05 (-80%)
主要措施:
- 图片 WebP 格式 + CDN
- 代码分割,首屏 JS 减少 60%
- 实现虚拟滚动
- 优化字体加载策略
结果:
- 页面加载速度提升 65%
- 转化率提升 23%
- SEO 排名上升
总结
性能优化是一个持续的过程,需要:
- 测量: 使用工具定期测试
- 分析: 找出瓶颈所在
- 优化: 逐步改进
- 监控: 持续跟踪指标
记住:优化要基于数据,不要过早优化!
想了解更多性能优化技巧?关注我的博客,我会持续分享实战经验。