浏览器缓存机制

246 阅读2分钟

通过以下几个部分来探讨浏览器缓存机制:

缓存位置 缓存策略 实际场景应用缓存策略

缓存位置

从缓存位置上来说分为四种,并且各自有优先级,当依次查找缓存且都没有命中的时候,才会去请求网络

Service Worker Memory Cache

Disk Cache

Push Cache 网络请求

Memory Cache 也就是内存中的缓存,读取高效,持续性很短。 一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。

Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。

Push Cache 当以上三种缓存都没有命中时,它才会被使用。并且缓存时间也很短暂,只在会话(Session)中存在,一旦会话结束就被释放。

缓存策略

通常浏览器缓存策略分为两种:强缓存和协商缓存,并且缓存策略都是通过设置 HTTP Header 来实现的。

强制缓存

强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control 。强缓存表示在缓存期间不需要请求

协商缓存

如果缓存过期了 ,就需要发起请求验证资源是否有更新。协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified 和 ETag 。

实际场景应用缓存策略:

1、频繁变动的资源

对于频繁变动的资源,首先需要使用 Cache-Control: no-cache 使浏览器每次都请求服务器,然后配合 ETag 或者 Last-Modified 来验证资源是否有效。但是能显著减少响应数据大小。

2、代码文件

对文件名进行哈希处理,只有当代码修改后才会生成新的文件名。基于此,我们就可以给代码文件设置缓存有效期一年 Cache-Control: max-age=31536000,这样只有当 HTML 文件中引入的文件名发生了改变才会去下载最新的代码文件,否则就一直使用缓存。

Service Worker:运行在浏览器背后的独立线程,一般可以用来实现缓存功能
Service Worker 实现缓存功能三个步骤:
1、注册 Service Worker
2、监听到 install 事件
3、通过拦截请求的方式查询是否存在缓存,
存在缓存的话就可以直接读取缓存文件,否则就去请求数据
if (navigator.serviceWorker) {
  navigator.serviceWorker
    .register('sw.js')
    .then(function(registration) {
      console.log('service worker 注册成功')
    })
    .catch(function(err) {
      console.log('servcie worker 注册失败')
    })
}
// sw.js
// 监听 `install` 事件,回调中缓存所需文件
self.addEventListener('install', e => {
  e.waitUntil(
    caches.open('my-cache').then(function(cache) {
      return cache.addAll(['./index.html', './index.js'])
    })
  )
})

// 拦截所有请求事件
// 如果缓存中已经有请求的数据就直接用缓存,否则去请求数据
self.addEventListener('fetch', e => {
  e.respondWith(
    caches.match(e.request).then(function(response) {
      if (response) {
        return response
      }
      console.log('fetch source')
    })
  )
})

参考:juejin.cn/book/684473…