tomoya06 / web-developer-guidance

Actually it's just a notebook for keeping down some working experience.
4 stars 0 forks source link

Frontend - 性能优化 #23

Open tomoya06 opened 3 years ago

tomoya06 commented 3 years ago

缓存

HTTP - 具体应用的缓存部分做系统总结。 总结参考了掘金小册 - 前端性能原理和实践

浏览器缓存机制有四个方面,它们按照获取资源时请求的优先级依次排列如下:

  1. Memory Cache
  2. Service Worker Cache
  3. HTTP Cache
  4. Push Cache

Memory Cache

存在内存中的缓存。特点如下:

Service Worker Cache

API参考MDN

Service Worker 是一种独立于主线程之外的 Javascript 线程。Service workers 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。他们还允许访问推送通知和后台同步API。

Service Worker特点总结如下:

HTTP Cache

分为强缓存和协商缓存。强缓存优先级较高,命中强缓存失败时会走协商缓存。

强缓存

相关请求头:expires / cache-control,浏览器会根据这两个字段来判断目标资源是否命中强缓存,若命中则直接从缓存中(memory cache 或 disk cache)获取资源,不会再与服务端发生通信,HTTP状态码为200。

image

expires

expires: Wed, 11 Sep 2019 16:12:18 GMT

expires 是一个时间戳,接下来如果我们试图再次向服务器请求资源,浏览器就会先对比本地时间和 expires 的时间戳,如果本地时间小于 expires 设定的过期时间,那么就直接去缓存中取这个资源。

缺点:服务端和客户端的时间设置可能不同

cache-control

HTTP/1.1新增字段。可以视作是 expires 的完全替代方案。可包含多种设置

cache-control: max-age=3600, s-maxage=31536000

完整用法参考MDN

协商缓存

相关请求头:Last-Modified / Etag。协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。

如果服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,这种情况下网络请求对应的状态码是 304(如下图)。

image

last-modified

Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT

Last-Modified 是一个时间戳,精度为秒。

如果我们启用了协商缓存,它会在首次请求时随着 Response Headers 返回;随后我们每次请求时,会带上一个叫 If-Modified-Since 的时间戳字段,它的值正是上一次 response 返回给它的 last-modified 值:

If-Modified-Since: Fri, 27 Oct 2017 06:35:57 GMT

服务器根据资源修改时间判断资源是否发生变化。若变化,则返回新的资源和last-modified值;若没有变化,则返回304响应。

image

ETag

ETag: W/"2a3b-1602480f459"

Etag 是由服务器为每个资源生成的唯一的标识字符串,类似于MD5。当首次请求时,我们会在响应头里获取到一个最初的ETag。那么下一次请求时,请求头里就会带上一个值相同的、名为 if-None-Match 的字符串供服务端比对了:

If-None-Match: W/"2a3b-1602480f459"

比较:

缓存选择

参考Chrome提供的流程图:

image

Push Cache

Push Cache 是指 HTTP2 在 server push 阶段存在的缓存。特点如下:

tomoya06 commented 3 years ago

浏览器存储

特性 cookie localStorage sessionStorage indexDB
数据生命周期 一般由服务器生成,可以设置过期时间 除非被清理,否则一直存在 页面关闭就清理 除非被清理,否则一直存在
数据存储大小 4K 5M 5M 无限
与服务端通信 每次都会携带在 header 中,对于请求性能影响 不参与 不参与 不参与

TIPS

tomoya06 commented 3 years ago

内容分发网络 CDN

Content Distribution Network, CDN 是指一种透过互联网互相连接的电脑网络系统,利用最靠近每位用户的服务器,更快、更可靠地将音乐、图片、视频、应用程序及其他文件发送给用户,来提供高性能、可扩展性及低成本的网络内容传递给用户。

请求实现过程

参考知乎文章

image

  1. 当用户点击网站页面上的内容URL,经过本地DNS系统解析,DNS系统会最终将域名的解析权交给CNAME指向的CDN专用DNS服务器。
  2. CDN的DNS服务器将CDN的全局负载均衡设备IP地址返回用户。
  3. 用户向CDN的全局负载均衡设备发起内容URL访问请求。
  4. CDN全局负载均衡设备根据用户IP地址,以及用户请求的内容URL,选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求。
  5. 区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务,选择的依据包括:根据用户IP地址,判断哪一台服务器距用户最近;根据用户所请求的URL中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力。基于以上这些条件的综合分析之后,区域负载均衡设备会向全局负载均衡设备返回一台缓存服务器的IP地址。
  6. 全局负载均衡设备把服务器的IP地址返回给用户。
  7. 用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容传送到用户终端。如果这台缓存服务器上并没有用户想要的内容,而区域均衡设备依然将它分配给了用户,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉到本地。
tomoya06 commented 3 years ago

图片懒加载

  1. 通过container.scrollTop + container.clientHeight - elem.offsetTop > 0判断已经露出,使用container.onscroll事件触发监听。参考自己实现代码
  2. 通过window.innerHeight - element.getBoundingClientRect().top >= 0或者document.documentElement.clientHeight - element.getBoundingClientRect().top判断已经露出,注意跟方法1的差异在于,本方法的容器只能是document。使用window.onscroll事件触发监听。参考掘金小册
  3. 通过IntersectionObserver API判断,参考掘金博客,以及MDN文档