前端性能优化可以从加载性能、运行性能、渲染性能、网络性能、代码质量、工程化优化、用户体验几个方面系统考虑。下面按照实际项目优化思路展开。
一、加载性能优化(首屏速度)
目标:让用户更快看到页面内容。
1. 减少资源体积
JavaScript 优化
- 删除无用代码(Tree Shaking)
- 压缩 JS
- 代码分割(Code Splitting)
- 按需加载
例如:
// 不推荐import{Button,Table}from'element-ui'// 推荐importButtonfrom'element-ui/lib/button'Webpack:
optimization:{splitChunks:{chunks:'all'}}效果:
main.js | |-- vendor.js | |-- 页面A.js | |-- 页面B.js用户访问页面 A 时,不需要加载 B 页面代码。
2. 路由懒加载
Vue 项目常用:
constUser=()=>import('@/views/User.vue')替代:
importUserfrom'@/views/User.vue'优势:
首次加载:
所有页面代码 ↓ 加载慢优化后:
首页代码 ↓ 需要时加载其他页面3. 图片优化
图片通常是前端最大资源。
优化方式:
使用合适格式
| 格式 | 场景 |
|---|---|
| WebP | 普通图片 |
| AVIF | 更高压缩 |
| SVG | 图标 |
| PNG | 透明图片 |
图片压缩
例如:
原:
banner.png 5MB优化:
banner.webp 200KB图片懒加载
<imgsrc="xxx.webp"loading="lazy"/>或者:
IntersectionObserver:
constobserver=newIntersectionObserver(entries=>{if(entries[0].isIntersecting){img.src=img.dataset.src}})4. 使用 CDN
静态资源:
用户 | CDN节点 | 图片/js/css而不是:
用户 | 公司服务器优势:
- 降低延迟
- 减少服务器压力
- 提高并发能力
二、网络性能优化
1. 减少 HTTP 请求
例如:
不好:
10个css 20个js 100张图片优化:
合并css 代码拆分 图片雪碧图2. 开启 HTTP 缓存
强缓存
响应:
Cache-Control: max-age=31536000浏览器:
第一次请求 ↓ 缓存 ↓ 一年内直接使用协商缓存
If-None-Match ETag流程:
浏览器 | 询问服务器 | 没变化 | 304 | 使用缓存3. 使用 HTTP/2
HTTP/1:
请求1 请求2 请求3HTTP/2:
一个连接 多个请求并行优势:
- 多路复用
- Header压缩
- Server Push
三、渲染性能优化
目标:
避免页面卡顿。
1. 减少 DOM 数量
DOM 越多:
浏览器计算成本 ↑例如:
不要:
<div><div><div>内容</div></div></div>减少无意义嵌套。
2. 避免频繁操作 DOM
差:
for(leti=0;i<10000;i++){document.body.innerHTML+=i}每次修改都会触发:
DOM更新 ↓ 重新布局 ↓ 重新绘制优化:
constfragment=document.createDocumentFragment()for(leti=0;i<10000;i++){fragment.append(i)}document.body.append(fragment)3. 减少重排(Reflow)
浏览器渲染:
JS | Style计算 | Layout布局 | Paint绘制 | Composite合成影响 Layout 的操作:
element.offsetHeight element.clientWidth element.style.width='100px'避免:
for(leti=0;i<1000;i++){el.style.width=i+'px'}优化:
一次修改:
el.className='large'4. 使用 transform 动画
不推荐:
left:100px;top:100px;会触发布局。
推荐:
transform:translate(100px,100px);只触发:
Composite性能更好。
四、JavaScript运行性能优化
1. 防抖 debounce
场景:
搜索框:
输入: a ab abc不要请求3次。
实现:
functiondebounce(fn,time){lettimerreturnfunction(){clearTimeout(timer)timer=setTimeout(()=>{fn()},time)}}2. 节流 throttle
场景:
滚动:
scroll事件 scroll事件 scroll事件限制执行频率:
functionthrottle(fn,time){letlock=falsereturnfunction(){if(lock)returnlock=truesetTimeout(()=>{fn()lock=false},time)}}3. 避免内存泄漏
常见:
定时器未清理
setInterval(()=>{},1000)组件销毁:
clearInterval(timer)事件未解绑
Vue:
mounted(){window.addEventListener('resize',fn)}beforeDestroy(){window.removeEventListener('resize',fn)}五、Vue 项目性能优化
1. 合理使用 computed
不好:
computed:{list(){returnthis.data.filter(...)}}每次依赖变化重新计算。
合理缓存:
computed:{activeList(){returnthis.list.filter(x=>x.active)}}2. 避免大数据响应式
例如:
data(){return{tableData:[10000条数据]}}Vue2 会:
遍历 ↓ Object.defineProperty ↓ 监听每个字段优化:
- 分页
- 虚拟列表
- 后端分页
3. 大表格使用虚拟滚动
普通:
10000 DOM节点虚拟:
20~50 DOM节点4. key 使用正确
错误:
<divv-for="(item,index) in list":key="index">数据变化:
重新复用错误节点推荐:
:key="item.id"5. 减少 watch
避免:
watch:{data:{deep:true,handler(){...}}}大对象 deep watch 非常消耗性能。
六、工程化优化
1. Webpack/Vite优化
开启压缩
Webpack:
TerserPlugin分包
splitChunks分析包大小
工具:
- webpack-bundle-analyzer
查看:
lodash 500KB echarts 1MB寻找优化点。
2. Tree Shaking
避免:
importlodashfrom'lodash'改:
importdebouncefrom'lodash/debounce'七、用户体验优化
1. 骨架屏
不要:
白屏3秒优化:
页面结构 ↓ 骨架 ↓ 真实数据2. Loading策略
例如:
小请求:
无需loading大请求:
显示loading避免闪烁:
delay 300ms3. 首屏优先
优先加载:
Header 导航 核心内容延后:
评论 推荐 统计八、性能指标(面试常问)
Core Web Vitals
| 指标 | 含义 | 目标 |
|---|---|---|
| LCP | 最大内容渲染 | <2.5s |
| FID | 交互响应 | <100ms |
| CLS | 布局稳定 | <0.1 |
常见指标
FP
First Paint
第一次绘制。
FCP
First Contentful Paint
首次内容出现。
TTI
Time To Interactive
页面可交互时间。
九、性能优化排查流程(实际项目)
推荐流程:
1. Chrome DevTools分析 ↓ 2. Network 看资源大小、耗时 ↓ 3. Performance 看JS执行、渲染 ↓ 4. Lighthouse评分 ↓ 5. 找瓶颈优化 ↓ 6. 再测试总结:前端性能优化检查清单
| 方向 | 手段 |
|---|---|
| 资源 | 压缩、Tree Shaking、分包 |
| 加载 | 懒加载、CDN、缓存 |
| 网络 | HTTP2、减少请求 |
| 图片 | WebP、压缩、懒加载 |
| JS | 防抖节流、减少计算 |
| DOM | 减少节点、避免重排 |
| Vue | computed、虚拟列表、减少响应式 |
| 工程化 | Webpack/Vite优化 |
| 体验 | 骨架屏、渐进加载 |
| 监控 | Lighthouse、Performance |