跳到主要内容

谈谈浏览器缓存

浏览器缓存主要是为了提高资源访问效率,浏览器缓存也可以叫HTTP缓存, HTTP缓存机制可以分为强缓存和协商缓存,对于强缓存,静态资源会直接在浏览器本地缓存直接获取,当强缓存没有命中的情况下,会走协商缓存请求服务器获取资源

八股文+理解上谈​

浏览器缓存也可以叫HTTP缓存, HTTP缓存机制可以分为强缓存和协商缓存,

以下区别:

  • 缓存优先级:优先级较高的是 强缓存,在强缓存的失效的情况下,才会走协商缓存

    • 当浏览器请求资源的时候,会先检查强缓存,如果强缓存还在资源的有效期内,则直接从缓存中加载资源,而不需要经过服务端,即不需要和服务端通信
  • 服务端通信请求:强缓存不需要与服务端通信,协商缓存依赖服务端通信的

    • 强缓存不发请求到服务器,协商缓存会发请求到服务器
  • 请求状态码:强缓存的请求状态码是 200, 协商缓存的请求状态码是 304

  • http响应头:强缓存和协商缓存设置的响应头是不同的

    • 强缓存的响应头设置 Cache-Control和``Expires`字段来实现

      • Cache-Control字段中的max-age指令用于设置资源在客户端缓存中的最长时间,单位是秒
      • Cache-Control: max-age=3600表示资源将在缓存中保存1小时
    • 协商缓存的响应头设置Last-Modified和ETag字段来实现

      • Last-Modified表示资源的最后修改时间,单位时间是秒
      • ETag表示资源的唯一标识符

协商缓存的Last-Modified和ETag理解?​

  • 精准程度
    • ETag优于 Last-Modified,ETag是根据文件资源内容生成的,(生成哈希值)可以理解为文件资源的指纹,所以可以很精准的判断资源是否发生变化
    • 由于Last-Modified的单位是秒,如果在资源在1秒内发生变化,那么Last-Modified这时候是没办法感知到变化了
  • 优先级
    • Etag 在感知文件变化上比 Last-Modified 更加准确,优先级也更高。当 Etag 和 Last-Modified 同时存在时,以 Etag 为准
  • 性能
    • Last-Modified优于 ETag,也比较容易理解,Last-Modified仅仅只是记录一个时间点,而 Etag需要根据文件的具体内容生成哈希值。生成的ETag需要服务端额外的开销,也是影响服务端的性能

ETag可以替代Last-Modified吗?​

  • Etag 并不能替代 Last-Modified,它只能作为 Last-Modified 的补充和增强的存在
  • 通常在协商缓存中,ETag和Last-Modified 是一起混合使用的
  • 有些场景下,只需要使用Last-Modified 就可以解决了,也避免了性能的开销,如果使用ETag,每次客户端请求,服务端都需要根据资源重新生成一个新的ETag, 对性能有影响

什么场景只需要Last-Modified?

  • 1、资源内容经常变化
    • 如果资源内容经常变化,并且修改的时间可以准确反应资源的变化的话,那么只需要Last-Modified就可以进行缓存验证了,避免了每次请求都需要生成新的ETag ,节省了服务端的计算

浏览器缓存目的:​

  • 减少重复数据请求,避免通过网络再次加载资源,节省流量。
  • 降低服务器的压力,提升网站性能。
  • 加快客户端加载网页的速度, 提升用户体验。

如何利用好缓存?​

  • 资源使用强缓存,设置cache-contro的max-age

    • 对于频繁变动的资源来说,设置cache-contro的no-cache,并且走协商缓存
      • 如果设置no-cache,表示浏览器在请求资源时不要直接使用缓存,而是要询问服务端验证资源有效性
    • 不经常变化的资源,设置cache-contro的max-age设置过期时间
  • 文件资源可以使用协商缓存,设置ETag

    • ETag 是由服务器为每个资源生成的唯一的标识字符串,只要文件内容不同,它们对应的 Etag 就是不同的
    • Etag 能够精准地感知文件的变化
  • 设置DNS预获取

    • DNS 请求需要的带宽非常小,但是延迟却有点高,预读取 DNS 能让延迟明显减少一些
  • 静态资源放在CDN,进行资源内容分发的网络加速

    • CDN可以缩减用户和服务器的距离, 提升静态资源加载效率
    • 浏览器对一个域名的并发数有限制,所以用CDN域名可以专门对加载静态资源
    • 注意: 只需要缓存JS、CSS等相关静态资源,不能缓存HTML和接口相关数据