性能优化
写在前边: 前端的性能优化无非就是响应时间(不是接口响应时间,而是资源加载和页面渲染的时间),以下会简单描述下部分性能优化的方法
代码层面
- 减少闭包(优化内存占用)
- 减少注释和冗余变量(打包工具大部分均可配置插件)
- 减少空格和多余换行,以及变量名压缩(打包工具可以处理)
- 在http/1.x环境下,应该考虑分域名进行处理资源和接口请求,在谷歌下,对于同一个域名同时只能进行六个链接,所以建议分域名处理前端资源
- 按需引用所需要的代码(部分打包工具在使用插件情况下也可以支持,类似
rollup
或者Snowpack
原生就支持),不可否认某些dead code
依旧可能打包,可以采用/*#_PURE_*/
注释来解决 - 长期不变的代码,类似运行库(vue、vuex、vue-router、pinia、react、react-dom之类的)可以打包成单个模块,可以更好利用缓存,减少资源请求
- 部分资源合理利用cdn进行快速请求
传输阶段
尽可能减少请求资源的链路,分域名请求资源
- gzip压缩代码,可以使用Nginx或者Apache服务器进行开启gzip压缩,前端如果有gz文件优先使用gz文件
- 雪碧图、小于多少kb的直接内联代码中,不单独使用一个链接(webpack是有雪碧图插件的)
- http/1.x 升级到http/2
cache (缓存)
强缓存
强制缓存就是直接从浏览器缓存查找该结果,并根据结果的缓存规则来决定是否使用该缓存的过程。
- 不存在该缓存结果和标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致)
- 存在缓存结果和标识,但结果已失效,强制缓存失效,则使用协商缓存
- 存在缓存结果和标识,并且结果未失效,强制缓存生效,直接返回该结果
控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,有服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:
- 协商缓存生效,返回304,服务器告诉浏览器资源未更新,则再去浏览器缓存中访问资源
- 协商缓存失效,返回200和请求结果
同样,协商缓存的标识也是在响应报文的HTTP头和请求结果一起返回给浏览器的,控制协商缓存的字段分别有:Last-Modified/If-Modified-Since
Etag/If-None-Match
其中Etag/If-None-Match
优先级比Last-Modified/If-Modified-Since
高
强制缓存优先于协商缓存,若强制缓存生效则直接使用缓存,若不生效则进行协商缓存,协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续使用缓存。
浏览器资源提示
浏览器的preload
和prefetch
区别就是,一个是当前页面就要用,另一个是下个页面可能会用到 详细介绍的文档地址https://www.w3.org/TR/resource-hints/#introductionopen in new window
Preload (预加载)
众所周知preload 是一个声明式 fetch,可以强制浏览器在不阻塞 document 的 onload 事件的情况下请求资源。预先加载资源,加载完毕直接执行。
比如场景: 某些网站中会用到字体,字体一般内嵌入css样式表,表现形式为
/* font.css */
@font-face: {
font-family: 'YaHei Consolas Hybrid';
src: url('xx/xx/x/xx/xx.ttf');
}
那么加载结束后就是加载font.css
然后在onload
后加载xx/xx/x/xx/xx.ttf
,在没有加载出字体前,浏览器一般会进行降级处理,诚然现在的网络环境很好了,但是不排除部分用户网络环境依旧不佳,在网络不佳情况下,加载完页面后,如果有字体加载进来,会进行闪烁后进行字体的更换,体验并不佳,这时候可以直接在head标签内采用预加载
<link src="xx/xx/x/xx/xx.ttf" rel="preload" as="font" type="font/ttf"/>
这样操作之后,不会阻塞document的document加载,并且可以将请求提到最前,大部分场景下,初次渲染时,字体就以加载完毕
Prefetch (预获取)
Prefetch 告诉浏览器这个资源将来可能需要,但是什么时间加载这个资源是由浏览器来决定的。大概率即将被访问到的资源可以使用prefetch提升性能和体验!
prefetch
在大多数浏览器中都是晚于onload
生命周期的
使用场景: 用户下个页面为二级页面,并且有些细碎的资源请求,或者一些常规图片,可以在一级页面添加上下个页面的资源请求,当然也要慎用,这样用户的体验会更较为顺滑
dns-prefetch (预解析)
即将进行解析的域名进行获取,在对该域名资源请求前进行dns解析,加快请求时的dns解析速度
场景:在一个系统中有多个子域名服务,例如在阿里云官网中会跳转一些服务,
<link rel="dns-prefetch" href="//query.aliyun.com">
<link rel="dns-prefetch" href="//gm.mmstat.com">
Preconnect(预连接)
preconnect链接关系类型用于指示将用于获取所需资源的来源。启动早期连接,包括 DNS 查找、TCP 握手和可选的 TLS 协商,允许用户代理掩盖建立连接的高延迟成本。。
可以用在以下场景: 你的资源有cdn资源,并且马上会用到,或者大概率要跳转别的连接页面,比如友链,或者按钮就是跳转网址,可以这么处理,但是兼容并不太好,但也可以使用,尚处于实验性质(2022-05-02编辑)
<link rel="preconnect" href="//example.com">
<link href="https://cdn.domain.com" rel="preconnect" crossorigin>