前端性能优化清单与实践
发表于更新于
字数总计:1.4k阅读时长:5分钟阅读量: 徐州
性能优化是前端开发中非常重要的一环。用户对页面加载速度的容忍度只有几秒,加载太慢会导致用户流失。这篇总结前端性能优化的常用手段。
一、加载性能优化
1.1 减少请求数量
资源合并
<link rel="stylesheet" href="bundle.css">
<script src="bundle.js"></script>
|
雪碧图
将多个小图标合并为一张图片,减少请求数:
.icon { background-image: url(sprite.png); background-position: -10px -20px; }
|
内联资源
对于很小的资源,可以直接内联:
<svg><path d="..."/></svg>
<style>.small{color:red;}</style>
|
1.2 减少资源体积
代码压缩
- HTML、CSS、JS 启用压缩
- 使用构建工具(Terser、CSSNano)
图片压缩
- 使用 WebP 格式
- 压缩 PNG、JPEG
- 使用 TinyPNG 等工具
Tree Shaking
使用 ES6 模块 + 构建工具自动删除未使用代码:
import { debounce } from 'lodash';
|
1.3 缓存策略
强缓存
location ~* \.(css|js|jpg|png)$ { expires 7d; add_header Cache-Control: public; }
|
协商缓存
location ~* \.(css|js)$ { add_header Last-Modified $date_gmt; add_header ETag $request_id; }
|
1.4 懒加载
图片懒加载
<img src="placeholder.jpg" data-src="real-image.jpg" class="lazy">
<script> const lazyImages = document.querySelectorAll('.lazy'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.src = entry.target.dataset.src; observer.unobserve(entry.target); } }); }); lazyImages.forEach(img => observer.observe(img)); </script>
|
路由懒加载
const routes = [ { path: '/home', component: () => import('./views/Home.vue') } ];
const Home = lazy(() => import('./Home'));
|
二、渲染性能优化
2.1 避免布局抖动(Layout Thrashing)
问题代码
elements.forEach(el => { const width = el.offsetWidth; el.style.width = width * 2 + 'px'; });
|
优化方案:分离读写
const widths = elements.map(el => el.offsetWidth);
elements.forEach((el, i) => { el.style.width = widths[i] * 2 + 'px'; });
|
2.2 使用 CSS 变换
.box { top: 100px; left: 100px; }
.box { transform: translate(100px, 100px); }
|
2.3 减少重绘重排
使用 class 批量修改
element.style.width = '100px'; element.style.height = '100px'; element.style.margin = '10px';
element.classList.add('new-style');
|
避免以下属性
width、height、margin、padding
top、left、right、bottom
offsetWidth、offsetHeight
使用以下属性只会触发重绘,不触发重排:
2.4 启用 GPU 加速
.animated { transform: translateZ(0); will-change: transform; }
|
三、图片优化
3.1 选择合适的格式
| 格式 |
适用场景 |
特点 |
| JPEG |
照片、复杂图像 |
体积小 |
| PNG |
图标、需要透明 |
支持透明、质量高 |
| WebP |
通用场景 |
体积更小 |
| SVG |
图标、简单图形 |
可缩放、体积小 |
| AVIF |
现代浏览器 |
体积最小 |
3.2 响应式图片
<img srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w" sizes="(max-width: 480px) 100vw, (max-width: 800px) 80vw, 60vw" src="medium.jpg" alt="描述">
|
3.3 图片加载策略
<link rel="preload" as="image" href="hero.jpg">
<img src="photo.jpg" loading="lazy" alt="...">
|
四、JavaScript 优化
4.1 防抖与节流
防抖(Debounce):等用户停止操作后才执行
function debounce(fn, delay) { let timer = null; return function(...args) { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); }, delay); }; }
window.addEventListener('resize', debounce(() => { console.log('resize'); }, 300));
|
节流(Throttle):限制执行频率
function throttle(fn, limit) { let inThrottle; return function(...args) { if (!inThrottle) { fn.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; }
window.addEventListener('scroll', throttle(() => { console.log('scroll'); }, 200));
|
4.2 虚拟滚动
长列表渲染优化:
4.3 Web Worker
处理耗时计算:
self.onmessage = ({ data }) => { const result = heavyComputation(data); self.postMessage(result); };
const worker = new Worker('worker.js'); worker.postMessage(largeData); worker.onmessage = ({ data }) => { console.log('结果:', data); };
|
五、字体优化
5.1 字体加载策略
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
@font-face { font-family: 'MyFont'; src: url('font.woff2') format('woff2'); font-display: swap; /* 先用系统字体,显示后再替换 */ }
|
5.2 字体子集化
只加载使用的字符:
@font-face { src: url('subset.woff2') format('woff2'); unicode-range: U+4e00-9fff; }
|
六、关键渲染路径优化
6.1 关键 CSS 内联
<head> <style> .header { background: #333; color: #fff; } .hero { height: 500px; } </style> </head>
|
6.2 非关键 CSS 异步加载
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">
|
6.3 脚本加载顺序
<script src="main.js" defer></script>
<script src="analytics.js" async></script>
|
七、性能监测工具
| 工具 |
用途 |
| Lighthouse |
综合性能审计 |
| Chrome DevTools |
性能分析 |
| WebPageTest |
页面加载分析 |
| Performance API |
实时监测 |
const timing = performance.getEntriesByType('navigation')[0]; console.log('DNS:', timing.domainLookupEnd - timing.domainLookupStart); console.log('TCP:', timing.connectEnd - timing.connectStart); console.log('DOM:', timing.domContentLoadedEventEnd - timing.navigationStart);
|
八、优化清单
加载阶段
渲染阶段
交互阶段
性能优化是持续的过程,建议定期用 Lighthouse 检测,发现问题及时优化。有其他问题欢迎留言!