前端性能优化
介绍
前端性能优化涉及到的东西很多,技巧也很多,但他们所遵守的规则是不变的,都是围绕着页面的生命周期进行的,所以首先要了解页面的生命周期。
一个页面的生命周期:
- 缓存检查,检查本地强缓存是否生效。
- DNS解析获取ip地址
- 建立TCP连接, 客户端发送Http请求
- 服务端响应请求,客户端下载资源
- 客户端解析并渲染页面,页面交互
各个阶段的性能优化手段
1. 本地强缓存检查
对资源合理的使用各级缓存手段
- 第三方库公共模块抽离
2. DNS解析获取ip地址
单个域名的典型DNS解析过程所花费的时间大概20-120 毫秒。
优化手段:
-
减少DNS的请求次数: 减少域名的数量
-
进行 DNS 预获取:dns-prefetch
<line rel="dns-prefetch" href="https://fonts.googleapis.com/">
3. 建立TCP连接, 客户端发送http请求
-
减少HTTP请求数量
一个完整的
HTTP请求需要经历DNS查找,TCP三次握手,浏览器发出HTTP请求,服务器接收、处理请求并返回响应,浏览器接收响应等过程。建立连接和下载数据都需要时间,应尽量将多个小文件合并为一个大文件,从而减少HTTP请求次数。例如:
- 雪碧图
- 避免 src属性或者href属性为空,虽然属性为空字符串,但浏览器仍然会向服务器发起一个HTTP请求。
-
使用高版本的http协议 因为高版本协议解决了低版本协议的一些痛点。比如 http1.1解决 http1.0短链接的问题。http2.0有头部压缩和多路复用,解决了http1.1头部阻塞的问题,http3解决了http2丢包的问题。
-
划分内容到不同的域名
浏览器一般会限制每个域的并行线程(一般为6个),使用不同的域名可以最大化下载线程,但注意保持在2-4个域名内,以避免DNS查询损耗。
例如,动态内容放在
csspod.com上,静态资源放在static.csspod.com上。
4. 服务端响应,客户端下载资源
-
使用CDN
内容分发网络(CDN)是一组分散在不同地理位置的web服务器,把内容部署在多个地理位置分散的服务器上能让用户更快地载入页面。
-
避免重定向
重定向会影响用户体验,尤其是多次重定向时,用户在一段时间内看不到任何内容,只看到浏览器进度条一直在刷新。
-
启用Gzip
Gzip压缩通常可以减少70%的响应大小,对某些文件更可能高达90%,非常高效。
-
尽量减小代码体积。
去除非必要的包和库。可以利用webpack的可视化资源分析工具webpack-bundle-analyzer,分析依赖内容。
使用esm的包和库,利用打包工具去进行 treeshaking删除无用代码。
利用压缩工具压缩代码。
-
减小cookie大小,cookie会在服务端和客户端的请求中自动携带。非必要的cookie会造成的流量浪费,影响响应速度。
- 去除不必要的 Cookie;
- 尽量压缩 Cookie 大小;
- 设置合适domain和path;
- 设置合适的过期时间。
5. 客户端渲染页面和页面交互
-
css放顶部,js放底部
先加载样式表,防止页面闪烁
js会阻塞dom数创建,最好放底部。或者使用
<script>的 defer 属性或者async属性。 -
减少回流重绘
当改变 DOM 元素位置或大小时,会导致浏览器重新生成渲染树,这个过程叫重排。
当重新生成渲染树后,就要将渲染树每个节点绘制到屏幕,这个过程叫重绘。
重排会导致重绘,重绘不会导致重排 。
重排和重绘这两个操作都是非常昂贵的,因为 JavaScript 引擎线程与 GUI 渲染线程是互斥,大量的重排重绘容易导致页面卡顿。
- 使用 translate代替 top/bottom 做动画,translate不会造成回流重绘。
- 对 DOM 元素执行一系列操作,可以将 DOM 元素脱离文档流,修改完成后,再将它带回文档,推荐使用隐藏元素(display:none)或文档碎片(DocumentFragement)。
- 用 JavaScript 修改样式时,使用替换 class 来改变样式,而不是多次操作style。
-
使用事件委托
利用事件冒泡原理,只指定一个事件处理程序,可以节省内存。
-
节流去抖
减少回调事件发生的频率,提升性能。
-
减少js运行中的长任务,避免页面卡顿
- 计算量大的任务,可以启用Web Worker,避免卡住主线程。
- 使用时间切片,将一个整体执行的js长任务,分片执行。
-
使用 requestAnimationFrame 来实现视觉变化
采用系统时间间隔,保持最佳绘制效率,浏览器专门为动画提供的API,如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销。
-
合理的代码逻辑和算法优化
避免内存泄漏,算法利用空间换时间等
-
减少页面dom节点数
使用虚拟滚动渲染大数据列表
-
框架性能优化
vue: 重复渲染频率较高的内容,抽离成单独组件,避免多余的重复渲染。
react :
使用purecomponents,shouldupdate, usememo,usecallback等api避免非必要的子组件渲染。
-
图片优化
图片懒加载
使用 webp 格式的图片,它具有更优的图像数据压缩算法,图片尺寸更小
尽可能利用 CSS3 效果代替图片
-
首屏优化
单页面项目使用路由分包,首屏如果用到了体积较大的包时,可以采用动态加载,即真正的使用时才加载包。
对首屏渲染时间要求较高,同时也要SEO要求的项目,可以考虑采用服务端渲染。
性能指标
谷歌自带插件 - LightHouse - 6大指标
-
First Contentful Paint 首次内容绘制 (FCP)
表示页面从开始加载到用户首次在屏幕上看到任何内容时的时间
-
Time to Interactive 可交互时间 (TTI)
表示⽹⻚第⼀次 完全达到可交互状态 的时间点,浏览器已经可以持续性的响应⽤户的输⼊。
-
Speed Index 速度指数
表示页面可视区域中内容的填充速度的指标,可以通过计算页面可见区域内容显示的平均时间来衡量。
-
Total Blocking Time 总阻塞时间 (TBT)
度量FCP 和 TTI 之间的总时间,在该时间范围内,主线程被阻塞足够长的时间以防止输入响应。
-
Largest Contentful Paint 最大内容绘制 (LCP)
可视区域中最大的内容元素(文本或图像)呈现到屏幕上的时间,用以估算页面的主要内容对用户可见时间。
-
Cumulative Layout Shift 累积布局偏移 (CLS)
整个页面生命周期内发生的所有意外布局偏移中最大一连串的布局偏移分数,它是⼀种保证⻚⾯的视觉稳定性从⽽提升⽤户体验的指标⽅案。
新一代性能指标 Web vitals
LCP:最大内容绘制时间
FID:首次输入延迟时间
CLS:累计布局偏移量
RAIL性能模型
这个名字的由来是四个英⽂单词的⾸字⺟:
- 响应(Response):应该尽可能快速的响应⽤户, 应该在 100ms 以内响应⽤户输⼊。
- 动画(Animation):在展示动画的时候,每⼀帧应该以 16ms 进⾏渲染,这样可以保持动画效果 的⼀致性,并且避免卡顿。
- 空闲(Idle):当使⽤ Javascript 主线程的时候,应该把任务划分到执⾏时间⼩于 50ms 的⽚段中
去,这样可以释放线程以进⾏⽤户交互。
- 加载(Load):应该在⼩于 1s 的时间内加载完成你的⽹站,并可以进⾏⽤户交互。