Adamwu1992 / adamwu1992.github.io

My Blog
2 stars 0 forks source link

浏览器缓存 #12

Open Adamwu1992 opened 5 years ago

Adamwu1992 commented 5 years ago

以下的表述是指在Chromium浏览器下的表现,其他的浏览器可能又不一样的实现。

优先级 持久化 命中规则 作用范围
Memory Cache 1 No URL Navigation
Service Worker 2 Yes 自定义 Host
HTTP Cache 3 Yes HTTP语义 Cros Sessions and Sites
PUSH Cache 4 No HTTP语义 HTTP/2 session

Memory Cache

内存缓存(Memory Cache)是一个巨大的资源容器,渲染引擎(renderer)在渲染当前文档期间抓取的所有的资源都储存在其中,并且在文档生命周期内一直存在。

但是Memory Cache是一个短期缓存,它只会在下一个导航前保存这些缓存,有些情况下可能更短。

有很多用情况你请求的资源已经被缓存在Memory Cache中了:

但是Memory Cache不会轻易的命中一个请求,除了要有匹配的URL,还要有相同的资源类型、CORS模式以及一些其他特性。

Memory Cache匹配规则在标准中没有详尽的描述,所以不同的浏览器内核在实现上会有所不同。

Memory Cache是不关心HTTP语义的,比如Cache-Control: max-age=0的资源,仍然可以在同一个导航中被重用。但是在特定的情况下,Memory Cache会遵守Cache-Control: no-store指令,不缓存相应的资源。

Service Worker

Memory Cache不同的是Service Worker没有任何预设的规则,它完全取决于开发者如何设置它。

Service WorkerMemory Cache主要的区别就是它是持久化的,即使tab页关闭或者浏览器重启,保存在Service Worker缓存里的资源不会消失。

一种删除Service Worker缓存的方法是使用JS代码,cache.delete(resource);还有一种导致缓存被删除的情况是触发了系统的存储空间上限,此时页面的Service Worker缓存连同indexedDB, localStorage等都会一起被回收掉。

Service Worker仅仅在某个限定的作用域内生效,大多数情况下仅对单个host内的文档发起的请求生效。

HTTP Cache

HTTP Cache也被叫做Disk Cache

首先,HTTP Cache是持久化的,并且允许跨session甚至是跨站点地重用。如果一个资源被一个站点缓存在HTTP Cache中,另一个站点如果有相同的请求,是可以重用的。

其次,HTTP Cache是遵循HTTP语义的。它总是会储存最新的资源,验证需要被验证的资源,拒绝储存它不应该储存的资源,这些都是由资源的响应头决定的。

既然它是一个持久化的缓存,就需要某种机制去删除缓存。和Service Worker不同的是它可以逐条删除,当浏览器需要空间去储存更加新鲜或者更加重要的缓存的时候,旧的缓存就会被删除。

HTTP Cache有一个基于缓存的组件,用来匹配请求的资源是否命中它已有的缓存资源,如果有发现命中的资源,它需要从硬盘里取获取这个资源,这是一个昂贵的操作。

我们之前提到HTTP Cache是遵循HTTP语义的,这几乎是完全正常的,只有一个例外的情况:当一个资源是为了下个导航被预抓取回来的(通过<link rel=prefetch>或者浏览器的其他内部逻辑),即使它是不可储存的,它也将会被保留到下个导航。所以当这些预抓取资源到达HTTP Cache时,它将被保留大约5分钟,并且期间不会被重新验证。

Push Cache

Push Cache是HTTP/2推送的资源存储的地方。它是HTTP/2会话的一部分。如果HTTP/2会话关闭了,储存在其中的资源都会消失。从不同的会话发起的请求将不会命中Push Cache中的资源。所有未被使用的资源在Push Cache会储存优先的时间(Chromium浏览器大约5分钟)。

Push Cache根据请求的URL以及请求表头来匹配资源,但是不是严格遵守HTTP语义的。

如果一个请求命中了Push Cache里的资源,那么这个资源将会从Push Cache里移除,然后经过HTTP Cache时,会保留一份拷贝缓存下来,再经过Service Worker(如果有)时,也会保留一份拷贝储存下来,最后请求的资源回到渲染引擎时,Memory Cache会存储一份对该资源的引用,如果将来本导航会话中的相同的资源请求,这份引用就可以直接被分配给该请求。

参考

xgqfrms commented 4 years ago

🕵️‍♂️这块内容,目前看来没有比较正确的答案呀

image

demo

image

image

Adamwu1992 commented 4 years ago

🕵️‍♂️这块内容,目前看来没有比较正确的答案呀

image

demo

image

image

我查阅了关于 preload 的文档,关于缓存的部分还没有被明确定义。

Conceptually, a preloaded response ought to be committed to the HTTP cache, as it is initiated by the client, and also be available in the memory cache and be re-usable at least once within the lifetime of a fetch group.

其中提到的在一个 fetch group 声明周期内,preload 回的资源至少被重用一次才是它最重要的使用场景,至于刷新 tab 后资源从哪里获取,据我观察 preload 目前还是遵循的 http 缓存语义。

xgqfrms commented 4 years ago

现在我是这么理解的,

  1. 首先所有的资源第一次加载后,都是存在 memory cache 里面的;浏览器然后,根据 http cache 策略(强缓存/协商缓存),判断某个资源是否要 写入 disk cache;
  2. 后面,刷新页面再次请求资源的时候,浏览器按照(暂不考虑 service worker 等其他缓存)memory cache > disk cache 的顺序依次查找资源,直到命中,或重新请求;