前端性能优化
减少整体加载时间:减小文件体积、减少http请求、使用预加载
使网站尽快可用:仅加载首屏内容,其他内容根据需要进行懒加载
平滑和交互性:使用css替代js动画、减少ui重绘
感知表现:耗时操作要给用户反馈,比如加载动画、进度条、骨架屏等
性能测定:性能指标、性能测试、性能监控持续优化
第一部分 性能评判的标准(性能指标)
RAIL性能模型
响应(response):应该尽可能快的响应用户,100ms内响应用户输入;
动画(animation):动画的每一帧应该以16ms渲染,配合当今大部分设备的60帧,避免卡顿;
空闲(idle):在使用js主线程的时候,应该把任务划分到执行时间小于50ms的片段中去,这样可以释放线程以进行用户交互
加载(load):应该在小于1s的时间内加载完你的网站,并且可以进行交互
基于用户体验的性能指标
First Contentful Paint(FCP) 浏览器首次绘制来自DOM内容的时间
内容必须是文本、图片、背景图、非白色的canvas或svg,以及正在加载中的web字体的文本
0--2s--4s--
LCP (largest Con Pain。。。)可视区域最大的内容元素呈现到屏幕上的时间
主要考虑到的元素有:/内的/
0--2.5s--4s--
FID (First Input Delay) 首次输入延迟
从用户第一次与页面交互到浏览器的实际能够响应交互的时间。
输入延迟是因为浏览器的线程在做别的事情,所以不能响应用户,此时浏览器正在解析和执行javascript;
哪些内容会受FID影响:
- 文本输入框、复选框、单选按钮
- 选择下拉菜单
- 链接
0--100ms--300ms--
TTI (Time to Interactive) 网页第一次完全达到可交互状态的时间点
0--3.8s--7.3s--
TBT (Total Block Time) 总阻塞时间
所有长任务超出时间的总和
0--300ms--600ms--
CLS (Cumulative Layout Shift) 累计布局偏移
0--0.1s--0.25s--
Speed Index 后面详解
Web Vitals
chrome提出的一个指标方案,将上面的好多指标简化为三个指标:
LCP/FID/CLS
只需要把这三个指标做好,性能就算是好的优化
第二部分 性能测试以及性能测试的工具
首先必须要有一个观念:不要通过单一指标来判定性能
Lighthouse 灯塔工具
可以直接在chrome调试工具中使用
检测得分
90 以上就是不错的
性能指标
在检测得分结果出来后,点击See calculator,有每个指标的详细评分以及占比情况,建议优先优化占比较高的
优化建议Opportunity和诊断结果
在检测结果出来后,下方Opportunity里会有优化建议,主要有以下方面
移除阻塞渲染的资源
预连接所要请求的源
降低服务端响应时间
适当调整图片大小
移除未使用的css
等等 具体看具体报告内容
仅供参考,具体话还得考虑生命周期匹配正确的优化方案
WebPageTest 网站
云服务器,提供了多个节点,支持多地点的测试结果
Chrome DevTools
第三部分 网站的整个生命周期
浏览器收到URL,开启网络请求线程;
发出完整的http请求
dns解析
就是将输入的URL解析出来,并且通过查找,将域名转换为ip地址
通信链路的建立
建立TCP连接,三次握手。关闭时四次挥手
在服务器收到请求之前,往往加入了反向代理服务器
服务器收到请求并具体处理
- 验证环节,如跨域验证、安全校验拦截等
- 通过验证之后,进入后台代码执行阶段,如具体的计算、数据库的查询等
- 完成计算后,以http响应数据的形式发送回请求的前端,结束本次请求
前后台之间的http交互和缓存相关机制
- 浏览器缓存等等
浏览器接收到数据包后的关键渲染路径(crp)
构建对象模型
首先浏览器会通过解析HTML和CSS文件,来构建DOM(文档对象模型)和CSSOM(层叠样式表对象模型)
之后将DOM和CSSOM合并渲染,Render Tree
js的解析过程
第四部分 优化方案
一、请求和响应优化
1、DNS解析优化
减少dns请求次数
dns-prefetch 预获取
比如在HTML文件最后有,这里是在处理完HTML之后要去请求dns,则可以在内加入 来进行dns的预获取
注意:仅在跨域时使用,不要指向自身;慎用,多页面重复预解析会增加查询次数;
更多dns优化,更多与后端相关
- 延长dns缓存时间
- 使用cdn加速域名
- 自己搭建dns服务
2、HTTP请求
-
减少请求数量
- 合并脚本和样式表
- 将图片嵌入css代码
3、避免重定向
4、压缩传输的数据资源
5、HTTP缓存(都是在服务端设置的,或者node中台设置,静态资源大部分是ngix设置的)
http缓存主要分为强制缓存和协商缓存,二者的主要区别在于判断缓存命中时,浏览器是否需要向服务端进行询问以协商缓存的相关信息,进而判断是否需要就响应内容进行重新请求。
《1》强制缓存
如果浏览器判断所请求的目标资源有效命中,就可以直接从强制缓存中返回请求响应,无需与服务器进行任何通信
实现:服务端在响应头里设置 'Cache-Control':'max-age=num' num就是设置的多久过期,单位是秒,此时,只要在过期时间内,发出的相同的请求都会走缓存,而不会去请求服务器
《2》协商缓存
在使用本地缓存之前,需要向服务器端发起一次GET请求,与之协商当前浏览器保存的本地缓存是否已经过期
实现:在响应头里的字段'Cache-Control':'no-cache'表示走协商缓存,'last-modified':'时间',表示这个资源的最后修改时间是什么时候。下次请求时,如果服务器判断未过期,则返回一个304响应码,便直接走缓存;如果过期,则返回新的资源
补充:可以在响应头中添加'etag':'基于文件内容生成的密码戳',以此来规避这个问题:当文件内容没变,但是文件名改变了,进而导致的走请求不走缓存。
补充:浏览器在请求时,将最后修改时间和etag带给服务端,服务端判断。前端基本无需操作。
《3》缓存决策
在规划缓存决策时,一般是以下步骤:
是否使用缓存?默认no-----如果使用缓存?是否进行协商缓存?是--设置no-cache/否-----是否会被代理服务器缓存?是--public/否--private(具体的查一查)----------配置强制缓存过期时间-----------配置协商缓存的etag
一般的缓存策略:
- 因为HTML文件因为内容会发生修改,设置为协商缓存;
- 图片文件:因为网站对图片基本都是更改,所以设置为强制缓存,且强制缓存的时间不宜过长。cache-control:max-age:86400
- style.css文件,也设置为强制缓存,但是为了触发更新,当文件改变时,文件名要发生改变。(这也是为什么打包工具会根据内容打包出不同的文件名),过期时间可以延长到一年 max-age:31536000
- 最后是js脚本,类似style.css设置,但其中因为有较多的用户私人信息,不想让中间代理缓存,则可为cache-control添加pravite属性
6、Service Worker缓存
实现离线弱网络环境下的页面加载以及页面的预加载,基于web weoker ,调用一些api,具体实现方法查文档;
也能实现请求不到资源时快速跳转到错误页面,而不会等待很久的白屏时间
开源框架:Workbox、sw-toolbox(封装了一些缓存策略)
7、CDN缓存
8、Push缓存
9、使用服务端渲染
ssr、react中的nextjs,vue中的nuxtjs