如何提高前端应用的性能
1. 代码优化
1.1 减少DOM操作
// 错误示范 - 频繁操作DOM
for(let i=0; i<100; i++) {
document.body.innerHTML += `<div>${i}</div>`;
}
// 正确示范 - 使用文档片段
const fragment = document.createDocumentFragment();
for(let i=0; i<100; i++) {
const div = document.createElement('div');
div.textContent = i;
fragment.appendChild(div);
}
document.body.appendChild(fragment);
1.2 使用事件委托
// 错误示范 - 为每个元素绑定事件
document.querySelectorAll('.btn').forEach(btn => {
btn.addEventListener('click', handleClick);
});
// 正确示范 - 事件委托
document.body.addEventListener('click', (e) => {
if(e.target.classList.contains('btn')) {
handleClick(e);
}
});
1.3 避免重绘和回流
// 错误示范 - 多次修改样式
element.style.width = '100px';
element.style.height = '200px';
element.style.margin = '10px';
// 正确示范 - 使用class或一次性修改
element.classList.add('new-style');
// 或
element.style.cssText = 'width:100px; height:200px; margin:10px';
2. 资源优化
2.1 图片优化
- 使用WebP格式替代JPEG/PNG
- 使用响应式图片(srcset)
- 懒加载非关键图片
<img src="placeholder.jpg"
data-src="image.webp"
class="lazyload"
alt="示例图片">
2.2 代码分割
// 动态导入
const module = await import('./module.js');
2.3 缓存策略
- 设置合适的Cache-Control头
- 使用Service Worker缓存资源
- 文件名哈希实现长期缓存
3. 网络优化
3.1 使用CDN
<script src="https://cdn.example.com/library.js"></script>
3.2 预加载关键资源
<link rel="preload" href="critical.css" as="style">
<link rel="preconnect" href="https://api.example.com">
3.3 压缩资源
- 启用Gzip/Brotli压缩
- 压缩图片(ImageOptim/TinyPNG)
- 压缩CSS/JS(UglifyJS/CSSNano)
4. 渲染优化
4.1 关键渲染路径优化
<head>
<!-- 关键CSS内联 -->
<style>/* 关键CSS */</style>
<!-- 非关键CSS异步加载 -->
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">
</head>
4.2 使用虚拟列表
// 使用react-window等库实现
import { FixedSizeList as List } from 'react-window';
<List
height={400}
width={300}
itemSize={50}
itemCount={1000}
>
{Row}
</List>
4.3 Web Workers处理耗时任务
// main.js
const worker = new Worker('worker.js');
worker.postMessage(data);
// worker.js
self.onmessage = (e) => {
const result = heavyComputation(e.data);
self.postMessage(result);
};
5. 监控与持续优化
5.1 性能指标监控
- 使用Lighthouse进行审计
- 监控FP/FCP/LCP等核心指标
- 使用Web Vitals API
import {getCLS, getFID, getLCP} from 'web-vitals';
getCLS(console.log);
getFID(console.log);
getLCP(console.log);
5.2 性能预算
// package.json
{
"performance-budget": {
"max-bundle-size": "200kb",
"max-image-size": "100kb",
"max-requests": 20
}
}
5.3 A/B测试优化
- 对比不同实现方案的性能
- 使用数据分析驱动优化决策
- 渐进式优化策略
6. 框架特定优化
6.1 React优化
// 使用React.memo
const MemoComponent = React.memo(Component);
// 使用useMemo/useCallback
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
6.2 Vue优化
// 使用v-once
<div v-once>{{ staticContent }}</div>
// 使用计算属性
computed: {
filteredList() {
return this.list.filter(item => item.active);
}
}
6.3 Angular优化
// 使用OnPush变更检测策略
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
7. 移动端优化
7.1 触摸事件优化
// 使用passive事件监听器
element.addEventListener('touchstart', handler, { passive: true });
7.2 避免300ms点击延迟
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7.3 内存管理
- 避免内存泄漏
- 及时清理事件监听器
- 使用WeakMap/WeakSet
8. 构建工具优化
8.1 Tree Shaking
// webpack.config.js
module.exports = {
optimization: {
usedExports: true,
}
};
8.2 持久缓存
// webpack.config.js
module.exports = {
cache: {
type: 'filesystem',
}
};
8.3 代码压缩
// vite.config.js
export default {
build: {
minify: 'terser',
}
};
9. 最佳实践总结
- 测量优先:优化前先用工具测量性能瓶颈
- 渐进增强:确保核心功能在低端设备上可用
- 按需加载:只加载当前需要的资源
- 缓存利用:最大化利用浏览器缓存机制
- 持续监控:建立性能监控体系
- 团队协作:将性能优化纳入开发流程
通过以上这些方法的组合应用,可以显著提升前端应用的性能表现,为用户提供更流畅的体验。