前言

继续挖坑啦,这个也是上次面试和面试官说了很多的一个问题来着,然后我来好好重新研究研究,试着来了解一下浏览器以及和它相关的一些的缓存机制。因为是坑,所以也是缓慢更新的,如果有错误欢迎提出哦!
文章部分是小结于《WebKit技术内幕》这本书关于浏览器本地缓存的文字和尾部列出文章的内容,然后HTTP相关的知识主要是来自于《图解HTTP》这本书哦~

强缓存(本地)

关于浏览器的本地缓存,我都以谷歌浏览器为核心开始搜集资料+测试啦
查看谷歌浏览器中的本地缓存资源只要输入下面的地址就可以:

chrome://cache

就可以看到本地缓存的文件,一个个URL排列,点开一个URL,就可以显示这个缓存的具体内容:
图片描述

浏览器资源

常见的资源主要有:HTML、JavaScript、CSS、图片、SVG、CSS Shader、视频、音频和字幕、字体文件、XSL样式表。

浏览器资源可以分为两类:

  • 主资源:HTML页面,或者下载项
  • 派生资源:比如HTML页面中内嵌的图片或者脚本链接

在WebKit内核中,是用不同的类来表示它们,有一个公共父类叫做CachedResource,也很好理解,就是缓存的资源。由此对应的子类比如:CachedCSSStyleSheet缓存的CSS样式表等等,以此类推。但是HTML比较特殊,它对应的类叫做CachedRawResource

资源加载器

WebKit有三种类型的加载器。

  1. 每种资源类型的特定加载器:只加载一种特定的资源,比如imageLoaderFontLoader,当请求资源时,加载器来负责加载。
  2. 缓存机制的资源加载器:所有特定加载器通过它(CachedResourceLoader类)查找并插入缓存资源。
  3. 通用资源加载器:ResourceLoader类,WebKit需要从网络/文件系统获取资源的时候由它负责。

请求过程

浏览器在发起请求的时候,会先去获取缓存的信息,再来决定是否向服务器发起请求。
WebKit如果在资源池寻找资源:

  • 找到了,就会拿出来用;
  • 没找到,创建一个新的CashedResource子类对象,向服务器发送请求。收到资源后放入缓存中。(使用的是LRU算法来进行资源池资源的替换)

浏览器是根据URL来判断不同的缓存内容
也就是假如有两个文件,虽然它们的文件可能是相同的,但只要URL不同,浏览器就不会认为是同一个,所以都会进行一次缓存。
实际操作一下,进入localhost127.0.0.1来缓存一些东西:
图片描述
图片描述
这个meituce/images/logo.png其实是同一张图,但是因为URL不一样,所以浏览器缓存了两次。

继续观察:
图片描述

通过控制台可以看到资源主要有两种,而且对应文件类型不同,来源也不太一样,强缓存得到的状态码是200 OK

  • from memory cache(图片、脚本)
  • from disk cache(css)

内存缓存&磁盘缓存

内存缓存 Memory Cache
放入内存中缓存,Webkit的内存缓存只是针对派生资源。

磁盘缓存 Disk Cache
放入磁盘中缓存,访问时不需要重新下载资源,直接从磁盘中获取。WebKit中也只能存储一些派生类资源。
存储形式为一个index.dat文件:URL + Response信息 + Content内容。
Response信息用于判断服务器上该Url的Content内容是否被修改。

这两者的区别是
退出浏览器进程时,内存缓存中的数据会被清空,而磁盘缓存的数据不会。

不严谨的实验:
图片描述
这个网站只有HTML是没有被缓存的,所以可以证实,派生资源被缓存到其中。
单独输入一个在原网页中缓存过的图片来获取,发现它不是从磁盘内存缓存中来:
图片描述

HTTP相关请求字段

expires

来源版本:HTTP 1.0
:GMT格式的时间字符串
判断方法:如果发送的时间在这个时间之前,就从本地读取缓存。

expires: Sun, 27 May 2018 09:15:15 GMT

cache-control: max-age=?

来源版本:HTTP 1.1
:cache-control操控缓存的工作指令,不同指令通过,分隔开;其中指令max-age的值为一个数字,表示过期时间,单位是秒。
判断方法:如果根据时间和max-age算出已经是<=0了,就说明时间超过了,需要从服务器去读取。

cache-control: max-age=691200
如果cache-control与expires同时存在的话,cache-control的优先级高于expires

协商缓存(经过服务器)

这部分的内容就和HTTP的内容相关联了,主要是几个字段。
if-XXX这种字段称为条件匹配,即只有当结果为真时,服务器才会执行请求。
协商缓存成功后得到的状态码是304 NOT MODIFIED

HTTP相关请求字段

if-Match / if-None-Match

来源版本:HTTP 1.1
这个要联系到一个响应字段Etag,即服务器会一开始返回一个Etag值,只有后面这个E-tag作为if-Match字段的值发送到服务器,服务器进行判断是否匹配,来确定是否过期。
若匹配不一致,返回412(Precondition Failed)状态码。
可以指定字段值为*,这样只要资源存在,服务器就会忽略Etag值。

If-Match: "bfc13a64729c4290ef5b2c2730249c88ca92d82d"

if-Modified-Since / if-Unmodified-Since

来源版本:HTTP 1.0
根据字面意思也可以知道,这是制定了一个时间,表示在这个时间后更改/未更改。
它可以根据Last-Modified字段来确定是否符合要求。

If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT

既然有if-Modified-Since,为何又有Etag和if-Match?

  • 文件可能会被修改,但内容不改变(改变只是修改时间),而前者会再次重新获取。
  • If-Modified-Since只能精确到秒。
  • 某些服务器不能精确文件的最后修改时间。

缓存服务器

缓存服务器是代理服务器的一种,缓存服务器帮客户端转发资源的时候,自己也会保存一份。请求的资源如果已经被缓存,则直接返回。

其他补充

还可以在谷歌控制台的Network面板,选择Disable cache来禁止使用缓存。
图片描述

推荐文章

由memoryCache和diskCache产生的浏览器缓存机制的思考
Web开发须知的浏览器内幕 缓存与存储篇
memoryCache和diskCache流程详解
http协商缓存VS强缓存


MOCHIKO
318 声望29 粉丝