性能优化"/>
7CRP前端性能优化
DNS
每一次DNS解析会使用20-120ms的时间
主要对于图片资源等静态资源使用
-
减少DNS请求次数
(一个网站中存多个域名,尽可能不要请求太多的服务器资源,但是这个一般不会实现,因为现在服务器分别存储不同的资源,服务器分离)
-
DNS预解析
<link rel="dns-prefetch" href="//g.alicdn">
http
- 资源合并压缩
- 字体图标
- Base64(小图做base64)
- Gzip
- 图片懒加载
- 数据延迟分批加载
- CDN资源(请求更快,请求离自己家最近的服务器的资源)
- 骨架屏
- 。。。。。。
常见http状态码
2xx表示成功的请求
200表示OK,正常返回信息
204 成功处理,没有内容。
206 范围请求响应
3xx表示重定向
301表示永久重定向,请求的网页已经永久移动到新位置
302表示临时重定向
304表示自从上一次请求以来,页面的内容没有改变过
4xx表示客户端错误
400请求报文存在语法错误
401表示认证失败(发送的请求需要通过HTTP认证)
403表示没有权限,服务器拒绝访问
404表示请求的资源不存在,一般是路径写错了
405表示请求方法不允许,一般是请求方法用错了
5xx表示服务器错误
500表示服务器执行请求时发生错误
503表示服务器暂时无法处理请求(超负载或正在停机维护)
TCP连接、断开为什么三次握手和4次挥手
三次握手:
目的:为了准确无误地将数据送达目标处,TCP协议采用了三次握手策略。
发送端首先发送一个带SYN标志的数据包给对方。接收端收到后,回传一个带SYN/ACK标志的数据包以示传达确认信息。最后,发送端再回传一个带ACK标志的数据包,代表握手结束,建立连接。
四次挥手:
为了持久连接,其特点是只要任意一端没有明确提出断开连接,则保持TCP连接状态;其好处是在于减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。另外,减少开销的时间,使HTTP请求和响应能更早结束,从而提高web页面的显示速度。
服务器端发送一个带FIN标记的数据包给客户端;客服端分两次发送带ACK、FIN标志数据包给服务端;服务端发送带ACK标志的数据包给客户端并断开连接
http协议不安全的原因,https是如何解决的
http不足之处:
1)通信使用明文,不加密,内容可能被窃听。
2)不验证通信方的身份,因此可能会遭遇伪装。
3)无法证明报文的完整性,所以有可能已遭篡改。
https:
1)用SSL(安全套接层)对通信线路进行加密
2)SSL有一种称为证书的手段,用于确定通信双方。通过使用证书,以证明通信方就是意料中的服务器,客户端持有证书即可完成个人身份的确认。
3)通过校验数字签名,将一段文本先用Hash函数生成消息摘要,然后用发送者的私钥加密生成数字签名,与原文文一起传送给接收者。接收者通过校验数字签名来确定完成性。
https的缺点:
1)https与http相比通信速度会更慢,SSL必须进行加密处理,服务器和客户端在加密解密的过程中会消耗更多的硬件资源导致处理速度变慢。
2)https通信,证书是必不可少的,而证书是需要花钱的。
前端中比较常见的攻击手段:
1)XSS攻击(攻击者想尽一切办法将可执行的代码嵌入到网页中)
xss:全称跨站脚本攻击(Cross-Site Scripting),简单的说就是攻击者通过在目标网站上注入恶意脚本并运行,获取用户的敏感信息如 Cookie、SessionID 等,影响网站与用户数据安全。
场景:用于带有用户保存数据的网站功能:论坛发布,商品评论,用户私信
原因:当攻击者通过某种方式向浏览器页面注入了恶意代码,并且浏览器执行了这些代码。
解决措施:渲染页面前都要先做 HTML 过滤,然后再渲染,对输入数据中的html标签< >进行转义 < > httpOnly
2)CSRF 攻击
CSRF 攻击全称跨站请求伪造(Cross-site Request Forgery),简单的说就是攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF的另一个特征是,攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。
策略:
CSRF自动防御策略:同源检测(Origin 和 Referer 验证)。
CSRF主动防御措施:Token验证 或者 双重Cookie验证 以及配合Samesite Cookie。
保证页面的幂等性,后端接口不要在GET页面中做用户操作。··1
浏览器渲染
浏览器地址栏键入URL后会发生什么
1)查找 disk cache 中是否有匹配,如有直接显示缓存内容
2)DNS域名解析
3)三次握手,建立连接,发送请求
4)服务器收到请求,处理请求,返回响应
5)4次挥手,断开TCP连接
6)浏览器根据返回数据进行页面渲染
页面优化
-
html方面
- 使用语义化标签,使网站结构明朗,
- 尽量精简代码
- 巧用script的async与defer
- 骨架屏
-
css方面
-
精简代码
-
对于动画,使用可以触发硬件加速的属性
-
根据上一点浏览器渲染流程,可以知道,当css树还没构建完成时,页面是不会渲染到浏览器界面的,这也是为什么当css下载过慢时,会出现白屏的现象。因此,为了避免让用户看到长时间的白屏时间,我们应该尽可能的提高css加载速度
1)使用CDN(因为CDN会根据你的网络状况,替你挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)
2)对css进行压缩(可以用很多打包工具,比如webpack,gulp等,也可以通过开启gzip压缩)
3)合理的使用缓存(设置cache-control,expires,以及E-tag都是不错的,不过要注意一个问题,就是文件更新后,你要避免缓存而带来的影响。其中一个解决防范是在文件名字后面加一个版本号)
4)减少http请求数,将多个css文件合并,或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)
5)利用媒体类型和查询来解除对渲染的阻塞。
-
-
js方面
- 合理使用闭包
- 最好少触发浏览器的回流操作
- 使用事件代理来处理点击等事件
应用缓存
缓存流程
有强缓存走强缓存,没有就走协商缓存
缓存位置
浏览器按照资源大小决定资源缓存的位置
- service Worker 浏览器独立县城进行缓存
- Memory Cache:内存缓存
- Disk Cache:硬盘缓存
- push 擦cache(http2中的推送缓存)
打开网页,输入地址,查找硬盘中是否有匹配,有则使用,没有就发送网络请求
普通刷新:tab没有关闭,可以从内存中读取,然后是硬盘
强制刷新:浏览器不适用缓存,发送的请求头带有(Cache-control:no-cache,为了兼容ie还带有Pragma:no-cache),服务器直接返回200
缓存方式
原文链接:.html
浏览器在第一次请求发生后,再次请求时:·
- 浏览器会先获取该资源缓存的header信息,根据其中的
expires
和cahe-control
判断是否命中强缓存
,若命中则直接从缓存中获取资源,包括缓存的header信息,本次请求不会与服务器进行通信; - 如果没有命中强缓存,浏览器会发送请求到服务器,该请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/IF-Modified-Since、Etag/IF-None-Match),由服务器根据请求中的相关header信息来对比结果是否命中协商缓存,若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取;否则返回最新的资源内容
来源:前端开发博客
强缓存
定义:用户发送的请求,直接从服务器缓存中获取,不发送请求到服务器,不与服务器产生交互行为
强缓存是利用http的返回头中的Expires
或者Cache-Control
两个字段来控制的,用来表示资源的缓存时间。
1. Expires
该字段是http1.0时的规范,它的值为一个绝对时间的GMT格式的时间字符串,比如Expires:Mon,18 Oct 2066 23:59:59
GMT。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。·
2. Cache-Control:max-age:xxxx
Cache-Control是http1.1时出现的header信息,主要是利用该字段的max-age
值来进行判断,它是一个相对时间,例如Cache-Control:max-age=3600,单位是秒,代表着资源的有效期是3600秒。cache-control除了该字段外,还有下面几个比较常用的设置值:
- no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
- no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
- public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
- private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
- max-age:从当前请求开始,允许获取的响应被重用的最长时间(秒)。
协商缓存
定义:用户发送的请求,发送到服务器后,由服务器判定是否从缓存中读取资源
协商缓存就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问,这主要涉及到下面两组header
字段,这两组搭档都是成对
出现的,即第一次请求的响应头带上某个字段(Last-Modified
或者Etag
),则后续请求则会带上对应的请求字段(If-Modified-Since
或者If-None-Match
),若响应头没有Last-Modified或者Etag字段,则请求头也不会有对应的字段。
Last-Modified`/If-Modified-Since
浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。
当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。
如果命中缓存,则返回304,并且不会返回资源内容,并且不会返回Last-Modify。
ETag/If-None-Match
与Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一个校验码。ETag可以保证每一个资源是唯一的**,资源变化都会导致ETag变化**。服务器根据浏览器上送的If-None-Match值来判断是否命中缓存。
与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化。
为什么要有Etag
你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
- 某些服务器不能精确的得到文件的最后修改时间。
Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
用户行为
用户刷新界面,永远都不会提取本地缓存的文件
实际问题分析
如文章开头所属,代码更新到线上后用户浏览器不能自行更新,我们不能要求客户在系统更新后都进行一次缓存清理的操作。·
到底该如何解决呢?
在资源请求的URL中增加一个参数,比如:js/mian.js?ver=0.7.1。这个参数是一个版本号,每一次部署的时候变更一下,当这个参数变化的时候,强缓存都会失效并重新加载。这样一来,静态资源,部署以后就需要重新加载。这样就比较完美的解决了问题。
另外一种方式,webpack在打包时,给文件配置hash值,每一次文件内容相同,文件名不同,就会触发更新
遗留问题
CDN:Content Delivery Network/Content Ddistribute Network,即内容分发网络
-
CDN缓存?
关于CDN与缓存(浏览器和CDN)
-
分布式系统 ?
-
负载均衡?
-
缓存资源的存储与读取,浏览器是以什么规则去区分memory cache , 还是disk cache ?
同,文件名不同,就会触发更新
遗留问题
CDN:Content Delivery Network/Content Ddistribute Network,即内容分发网络
-
CDN缓存?
关于CDN与缓存(浏览器和CDN)
-
分布式系统 ?
-
负载均衡?
-
缓存资源的存储与读取,浏览器是以什么规则去区分memory cache , 还是disk cache ?
更多推荐
7CRP前端性能优化
发布评论