目录
前言
随着Web应用复杂度不断提升,前端性能优化变得尤为重要。本文将系统性地介绍从资源加载到页面渲染的全链路性能优化策略,帮助开发者构建高效、流畅的Web应用。
网络请求优化
DNS预解析
<link rel="dns-prefetch" href="//example.com">
HTTP缓存策略
- 强缓存:Cache-Control、Expires
- 协商缓存:ETag、Last-Modified
CDN加速
将静态资源部署到CDN,利用地理位置分布式节点加速资源访问。
HTTP/2和HTTP/3
利用多路复用、服务器推送等特性提升传输效率。
减少HTTP请求
- CSS Sprites
- 小图片内联为base64
- 组件库按需加载
- 合理合并资源文件
资源加载优化
资源压缩
- JavaScript和CSS压缩:移除空白、注释、简化变量名
- 图片压缩:WebP、AVIF等现代格式
- Gzip/Brotli压缩传输
资源优先级
<link rel="preload" href="critical.css" as="style">
<link rel="preconnect" href="https://api.example.com">
<link rel="prefetch" href="next-page.js">
懒加载
// 图片懒加载
const lazyImages = document.querySelectorAll('img.lazy');
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
lazyImages.forEach(img => observer.observe(img));
代码分割
// React中使用React.lazy和Suspense
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
JavaScript执行优化
避免阻塞渲染
<script async src="async-script.js"></script>
<script defer src="defer-script.js"></script>
Web Workers
将复杂计算移至后台线程,保持主线程流畅。
const worker = new Worker('worker.js');
worker.postMessage({ data: complexData });
worker.onmessage = function(event) {
const result = event.data;
updateUI(result);
};
优化事件处理
使用事件委托和节流/防抖。
// 防抖
function debounce(fn, delay) {
let timer = null;
return function() {
const context = this;
const args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(context, args);
}, delay);
};
}
// 使用防抖处理搜索输入
const searchInput = document.getElementById('search');
const debouncedSearch = debounce(search, 300);
searchInput.addEventListener('input', debouncedSearch);
渲染优化
优化DOM操作
- 批量更新DOM
- 使用文档片段(DocumentFragment)
- 避免强制重排(reflow)
// 优化前
for (let i = 0; i < 1000; i++) {
document.body.appendChild(document.createElement('div'));
}
// 优化后
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
fragment.appendChild(document.createElement('div'));
}
document.body.appendChild(fragment);
CSS优化
- 避免使用复杂选择器
- 减少重排属性的使用(如width、height、margin等)
- 使用transform和opacity进行动画
虚拟列表
处理大数据量列表时,只渲染可视区域内的元素。
class VirtualList {
constructor(container, itemHeight, totalItems, renderItem) {
this.container = container;
this.itemHeight = itemHeight;
this.totalItems = totalItems;
this.renderItem = renderItem;
this.visibleItems = Math.ceil(container.clientHeight / itemHeight) + 5;
this.scrollTop = 0;
this.startIndex = 0;
this.init();
}
init() {
this.container.style.position = 'relative';
this.container.style.height = `${this.totalItems * this.itemHeight}px`;
this.container.style.overflow = 'auto';
this.container.addEventListener('scroll', () => {
this.onScroll();
});
this.renderVisible();
}
onScroll() {
this.scrollTop = this.container.scrollTop;
this.startIndex = Math.floor(this.scrollTop / this.itemHeight);
this.renderVisible();
}
renderVisible() {
this.container.innerHTML = '';
for (let i = this.startIndex; i < this.startIndex + this.visibleItems; i++) {
if (i >= 0 && i < this.totalItems) {
const item = this.renderItem(i);
item.style.position = 'absolute';
item.style.top = `${i * this.itemHeight}px`;
this.container.appendChild(item);
}
}
}
}
用户体验优化
骨架屏
在内容加载前显示页面框架,减少用户等待感知。
<div class="skeleton">
<div class="skeleton-header"></div>
<div class="skeleton-content">
<div class="skeleton-line"></div>
<div class="skeleton-line"></div>
<div class="skeleton-line"></div>
</div>
</div>
.skeleton {
padding: 15px;
background: #fff;
}
.skeleton-header, .skeleton-line {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
.skeleton-header {
height: 30px;
margin-bottom: 15px;
border-radius: 4px;
}
.skeleton-line {
height: 15px;
margin-bottom: 10px;
border-radius: 2px;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
渐进式加载
- 关键CSS内联
- 图片渐进式加载
<style>
/* 关键CSS内联 */
.header { /* 样式 */ }
.hero { /* 样式 */ }
/* 其他首屏关键样式 */
</style>
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">
优化首屏内容
- 精简首屏HTML和CSS
- 核心内容优先渲染
性能监控与分析
性能指标
- FCP (First Contentful Paint):首次内容绘制
- LCP (Largest Contentful Paint):最大内容绘制
- FID (First Input Delay):首次输入延迟
- CLS (Cumulative Layout Shift):累积布局偏移
性能监控实现
// 监控FCP
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log(`FCP: ${entry.startTime}`);
// 上报数据
}
}).observe({type: 'paint', buffered: true});
// 监控LCP
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
const lastEntry = entries[entries.length - 1];
console.log(`LCP: ${lastEntry.startTime}`);
// 上报数据
}).observe({type: 'largest-contentful-paint', buffered: true});
// 监控CLS
let clsValue = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
console.log(`CLS: ${clsValue}`);
// 上报数据
}
}
}).observe({type: 'layout-shift', buffered: true});
调试工具
- Chrome DevTools Performance面板
- Lighthouse
- WebPageTest
总结
前端性能优化是一个系统工程,涵盖从网络请求、资源加载到页面渲染的全链路过程。本文介绍的优化策略不是孤立的,它们相互配合,共同构建高性能的前端应用。针对不同项目和场景,开发者需要根据实际情况选择合适的优化方案,并通过持续监控和分析,不断优化用户体验。