一、浏览器缓存分类
强缓存:浏览器从本地缓存获取,不需要发起服务器请求
协商缓存:发起一次服务器请求,服务器判断缓存是否过期,如果未过期返回304,浏览器从本地缓存读取;如果过期,返回对应资源,状态码为200
浏览器访问资源流程:
1. 判断本地是否有缓存,没有缓存则请求服务器重新获取;
2. 有缓存,判断是否是强缓存,如果是强缓存则直接返回200,不请求服务器。
3. 如果是协商缓存,请求服务器,判断缓存是否过期,如果未过期返回304,浏览器从本地缓存读取;如果过期,返回对应资源,状态码为200
二、强缓存
相关头部字段
pragma:值只有no-cache,是一个在 HTTP/1.0 中规定的通用首部,这个首部的效果依赖于不同的实现,所以在“请求-响应”链中可能会有不同的效果。它用来向后兼容只支持 HTTP/1.0 协议的缓存服务器,那时候 HTTP/1.1 协议中的 Cache-Control 还没有出来。所以建议只在需要兼容HTTP/1.0的场景下使用该属性,其他情况下建议使用cache-control。
cache-control:通用消息头字段,被用于在http请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。具体参数参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control
expires:响应头包含日期/时间(GMT格式),即这个时候之后,响应过期。
字段优先级
pragma > cache-control > expires
三、协商缓存
相关头部字段,其中请求头和响应头是配套使用的
1. 请求头 if-modified-since 和响应头 last-modified:两个属性都是GMT格式的时间戳,精确到秒,if-modified-since告诉服务器浏览器获取的上次修改时间,服务器取到该时间之后,与资源最新修改时间对比,如果有变化,返回新资源,状态码200,并将if-modified-since的值设置为last-modified的值;若无变化,返回304,浏览器从本地缓存中读取。
2. 请求头 if-none-match 和响应头 etag:if-none-match 是一个条件式请求首部。对于 GET和 HEAD 请求方法来说,当且仅当服务器上没有任何资源的 etag 属性值与这个首部中列出的相匹配的时候,服务器端会才返回所请求的资源,响应码为 200 。对于其他方法来说,当且仅当最终确认没有已存在的资源的 etag 属性值与这个首部中所列出的相匹配的时候,才会对请求进行相应的处理。在请求头同时存在 if-none-match 和 if-modified-since 时,if-modified-since 会被忽略,除非服务器不支持 if-none-match。
MDN 上对 etag 的描述是:
它们是位于双引号之间的ASCII字符串(如“675af34563dc-tr34”)。 没有明确指定生成ETag值的方法。 通常,使用内容的散列,最后修改时间戳的哈希值,或简单地使用版本号。 例如,MDN使用wiki内容的十六进制数字的哈希值。
etag 属性之间的比较采用的是弱比较算法,即两个文件除了每个比特都相同外,内容一致也可以认为是相同的。例如,如果两个页面仅仅在页脚的生成时间有所不同,就可以认为二者是相同的。
last-modified 和 etag 相比较:
1. last-modified 的精确度是秒,相比来说,etag 更加精确。
2. last-modified 是每次文件修改都会对应修改,即使文件内容并没有改变,相比来说,etag 可以避免部分文件内容未修改的缓存更新。