前端浏览器缓存的好处和弊端以及如何处理弊端

浏览器缓存

好处:

  1. 减少冗余的数据传输,节省带宽。
  2. 减轻服务器的请求压力,因为有缓存可以减少向服务器发送请求,
  3. 资源从缓存中读取,加快客户端的访问速度。因为无需从服务器请求等待响应

缺点:

  1. 系统更新时,如何删除浏览器的缓存资源,加载最新的页面。

缓存

  1. Service Worker:是一种独立于主线程之外的 Javascript 线程。它脱离于浏览器窗体,可以帮我们实现离线缓存、消息推送和网络代理等功能。

  2. Memory Cache:存在内存中的缓存。包括当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。因为存储在内存中,MemoryCache 是响应速度最快的一种缓存,但由于同样的原因,缓存持续性很短,会随着进程的释放而释放,一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。

  3. Disk Cache:Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。

  4. Push Cache:Push Cache 是 HTTP2 在 server push 阶段存在的缓存,当以上三种缓存都没有命中时,它才会被使用,Push Cache 是一种存在于会话阶段的缓存,当 session 终止时,缓存也随之释放。不同的页面只要共享了同一个 HTTP2 连接,那么它们就可以共享同一个 Push Cache。

强缓存

不会向服务器发送请求,直接从缓存中读取资源。状态码 200,显示 from disk cache 或 from memory cache。设置两种 Http Header 实现:Expires 和 Cache-Control

  • Expires:值是一个时间戳,表示本地时间到这个设置的时间缓存就失效。
    • 缺点:受限于本地时间
    • 推荐使用 Cache-Control
  • Cache-Control:优先级比 Expires 高,可以在请求头或者响应头中设置
    1. private:默认:只能在浏览器中缓存,只有在第一次请求中访问服务器。如有 max-age:缓存期间不访问服务器
    2. public:可以被任何缓存区缓存,如浏览器、服务器、代理服务器
    3. no-cache: 可以缓存,相当于协商缓存,每次都需要去服务器验证缓存是否一致。如有 max-age:缓存期间不访问服务器
    4. no-store:不仅不能缓存,连暂存也不可以
    5. max-age:以秒为单位的缓存时间,设置时间内,均使用本地的缓存,不再向服务器发起请求
    6. s-magage=:跟 max-age 作用一样,只在代理服务器中生效。优先级高于 max-age,只对 public 缓存有效,
    7. must-revalidate:可缓存但必须再想源服务器进行确认
    8. proxy-revalidate:要求中间缓存服务器对缓存的响应有效性进行确认

协商缓存

当 cache-control 和 Expires 过期或者它的属性设置为 no-cache 时,那么浏览器第二次请求时就会与服务器进行协商,判断资源是否更改,

  • 没更改返回 304 Not Modified,使用本地缓存资源。

  • 资源更改,返回 200,重新加载,本次缓存资源更新。

    浏览器与服务器的交互依靠 Last-Modified/If-Modified-Since、ETag/If-None-Match 的 header 头属性,在请求头和响应头成对出现的。

  1. Last-Modified/If-Modified-Since:

浏览器在第一次访问资源,或缓存过期后访问,服务器返回资源的同时,在 response header 中添加 Last-Modified 的 header,值是这个资源在服务器上的最后修改时间,浏览器接收缓存文件和 header 信息。随后我们每次请求时,浏览器会自动带上一个叫 If-Modified-Since 的时间戳字段给服务器,它的值正是上一次 response 返回给它的 Last-modified 值,然后服务器会根据 If-Modified-Since 的值对比资源的最后修改时间判断资源是否进行了修改更新。

  1. ETag/If-None-Match :

Etag 是由服务器为每个资源生成的唯一的标识字符串,这个标识字符串是基于文件内容编码的,只要文件内容不同,它们对应的 Etag 就是不同的,因此 Etag 能够精准地感知文件的变化。Etag 和 Last-Modified 类似,当首次请求时,我们会在响应头里获取到一个最初的标识符字符串。那么下一次请求时,浏览器就会在请求头里就会带上一个值相同的、名为 if-None-Match 的字符串供服务器比对。Etag 的优先级会比 Last-Modified 高,但是 Etag 因为要生成,也会更消耗服务器性能。

Cache-Control: no-cache 和 Cache-Control: no-store 区别

看字面意思容易误解,no-cache 就是不缓存,但是 no-cache 并不是不缓存,而是使用协商缓存,所以并不能禁止缓存,no-store 才是真正的禁止缓存。从节省带宽角度讲,使用 no-cache 更优一点,文件未发生改变时只传输很小的报文大小,只有在文件改变时才会传输整个文件大小。而不是 no-store 不管什么情况都传输整个文件大小。

Pragma: no-cache:和 Cache-Control: no-cache 区别

Pragma: no-cache 跟 Cache-Control: no-cache 相同,Pragma: no-cache 兼容 http 1.0 ,Cache-Control: no-cache 是 http 1.1 提供的。因此,Pragma: no-cache 可以应用到 http 1.0 和 http 1.1,而 Cache-Control: no-cache 只能应用于 http 1.1.

如何保证系统实时更新

方法一:
以 vue 为例,vue 在打包的时候,css 和 js 名字都加了哈希值,所以改动后打包生成的 js 和 css 是唯一的,页面请求的是新资源,不会有缓存问题。但是入口文件 index.html 会因为缓存造成更新问题,如果我们更新了,但是浏览器使用的是缓存,就会出现问题。所以需要对入口文件设置不使用强制缓存,需要每次去服务器验证文件是否修改,即使用协商缓存。

server {
  listen       80;
  server_name  域名;
  root   文件目录;
  index  index.html;
  location  {
  // 不加这一句,会出现nginx欢迎页面,无法正确加载资源
  try_files $uri /index.html;
  }
  location ~ .*\.(html)$ {
    // 对html文件限制缓存
    add_header Cache-Control no-store;
     // 不缓存
     // 或者用add_header Cache-Control no-cache;替代上面那一句,协商缓存
     add_header Pragma no-cache
  }
}

方法二:

  1. 最直接的办法
    Internet 选项 -> Internet 临时文件“设置” -> “每次访问此页时检查”,缺点是要设置每台客户端,客户端较多时不可取

  2. 设置网页头(header)

状态码

  1. 200 from memory cache
    • 状态码是灰色的,从内存中读取缓存的资源,强缓存。不请求服务器。
    • 页面关闭会被内存释放,再次打开相同页面需要重新请求服务器,然后重新缓存在浏览器
    • 脚本、字体、图片会被存放在内存中
  2. 200 from disk cache
    • 状态码是灰色的,从磁盘中读取缓存的资源,强缓存,不请求服务器。
    • 页面关闭不会被释放,这部分资源存在电脑磁盘中,只有用户手动清除浏览器缓存才会被释放。
    • 较大的 css 文件、js 文件和 jpg 图片会存入硬盘
  3. 200
    • 服务器请求响应的数据
  4. 304
    • 协商缓存。请求访问服务器,发现资源没有更新,使用本地资源。

磁盘和内存的区别

  1. 内存是计算机的工作场所,磁盘是用来存放暂时不用的信息
  2. 信息保存不同,内存中的信息会随刷新丢失,磁盘中的信息可以长久保存(除非手动删除)
  3. 磁盘的容量远大于内存
  4. cpu 只能读取内存里的数据,磁盘是作为存储空间的。

浏览器三级缓存原理

  1. 先查找内存,如果内存中存在,从内存中加载
  2. 如果内存中未找到,选择硬盘获取,如果硬盘中有,从硬盘中加载
  3. 如果硬盘中未找到,那就请求服务器,重新加载资源,加载到的资源缓存到硬盘和内存。

你可能感兴趣的:(前端,缓存)