深入理解HTTP/浏览器缓存机制

概述

浏览器请求资源时,并不是直接发起http请求,而是会先检查本地有没有该文件的缓存,如果本地有未过期缓存,那么就不用发起http请求了,直接使用本地缓存(强缓存),这样可以大大加快网页响应速度;如果本地有缓存但是过期了,那么浏览器需要向服务器发起一个http请求询问该文件有没有修改过,如果有修改过,服务器返回新的文件,如果没有修改过,服务器返回304状态码及空响应体,浏览器收到该响应后会继续使用本地缓存(协商缓存)

缓存的目的就是减少不必要的资源加载时间,加快网页响应速度,提升用户体验。

那么,在整个过程中,浏览器如何判断缓存是否过期?缓存的位置在哪里?服务器如何判断文件是否修改过?带着这些问题我们继续往下看

缓存的两个阶段:强缓存协商缓存

强缓存

强缓存的过程 :当浏览器首次请求资源时,服务器会将缓存规则放在http响应头字段里和响应体一同返回给浏览器,控制强缓存的响应头字段是ExpiresCache-Control ,浏览器收到后,会将响应结果和缓存标识存入浏览器缓存中,当下次再次请求该资源时,会先在缓存里查找,如果找到了并且未过期,则直接使用该缓存,不再发送http请求,此时network里的状态码是一个灰色的200。

Expires:HTTP1.0 的特性,标识该资源过期的时间点。它的值是标准时间格式,如 Wed, 22 Nov 2019 08:41:00 GMT。即在这个时间点之后,缓存的资源过期。

缺点:服务端和客户端时间不一致的话,就会有误差。

Cache-Control

是HTTP1.1 提出的特性,主要为了弥补Expires的缺陷,取值为:

max-age:xxx(number):有效时间xxx秒,是一个相对值

public:客户端和代理服务器都可以缓存

private:只有客户端可以缓存

no-cache:走协商缓存,与服务器确认文件是否修改

no-store:不缓存,请求最新资源

s-maxage:针对代理服务器的缓存时间

注意:为了兼容各版本http协议,通常两个头部同时设置,当同时存在时,Cache-Control比Expires优先级高。

缓存的位置

打开浏览器network tab的size列,可以看到缓存的位置:

from memory cache(内存缓存)

存在于当前进程中,容量小,读取速度快。

存活时间短,当浏览器标签页关闭时,进程结束,内存缓存也就不存在了

from disk cache(硬盘缓存)

存在于磁盘中,容量大,需要I/O读写操作,所以速度比内存缓存慢

不随进程的结束而销毁,存储时间长

注意⚠️:刚开始从硬盘中读取,读取之后将比较小的文件保存在内存中,所以当刷新页面,部分文件的缓存位置会变为from memory cache

协商缓存

协商缓存过程:

当强缓存时间过期了,才会进入协商缓存阶段,上面说到,首次请求时服务器会将缓存相关的头字段放入响应报文里,其中也包含协商缓存相关的头字段,如Last-Modified 和Etag, 当强缓存失效时,浏览器会携带协商缓存字段If-Modified-Since和 If-None-Match 向服务器发起请求,If-Modified-Since 的值就是服务器之前返回的Last-Modified 的值,If-None-Match 的值就是Etag的值, 服务器根据此头字段判断文件在上次请求后有没有修改过,如果没有修改过,返回状态码304,并且响应体为空加快传输速度,如果修改过,返回200状态码和新文件内容。

Last-Modified / If-Modified-Since

HTTP1.0 的特性,Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间。当强缓存失效,浏览器会携带If-Modified-Since向服务器发起请求,服务器收到该请求,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件。

缺陷:

  1. Last-Modified精度只有秒级,当在一秒内再次请求该资源,即使文件修改过,也会返回304,导致客户端使用了旧的缓存。
  2. 编辑了文件,但内容并没有更改,(比如加一个字然后又把它删了)这样也会造成缓存失效。

Etag / If-None-Match

HTTP1.1 的特性,Etag是服务器响应请求时,返回当前资源文件的一个唯一标识,它是根据实体内容生成的一段 hash 字符串,由服务端产生。每当文件有修改,hash都会重新生成,就会与之前的不一样,服务器由此判断文件被修改过。

当强缓存失效,浏览器会携带If-None-Match向服务器发起请求,服务器收到该请求,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200

注意⚠️:为了兼容各版本http协议,通常两种头部字段同时设置,当同时存在时,Etag / If-None-Match比Last-Modified / If-Modified-Since优先级高。

Etag 对比 Last-Modified

1.在精准度上,ETag优于Last-Modified

  • Last-Modified精度只有妙级

  • 如果编辑了文件,但内容并没有更改,(比如加一个字然后又把它删了)Last-Modified也会改变

2.在性能上,Last-Modified优于ETag

  • Last-Modified仅仅只是记录一个时间点,而 Etag需要根据文件的具体内容生成哈希值,需要使用哈希算法去计算,有一定的时间复杂度。

总结

用一个思维导图总结:

相关推荐
csdnLN25 分钟前
$.ajax() 对应事件done() 、fail()、always() 的用法
前端·javascript·ajax
甜味橘阳25 分钟前
echarts地图可视化展示
前端·javascript·echarts
bloxed1 小时前
前端文件下载多方式集合
前端·filedownload
余生H1 小时前
前端Python应用指南(三)Django vs Flask:哪种框架适合构建你的下一个Web应用?
前端·python·django
LUwantAC1 小时前
CSS(四)display和float
前端·css
cwtlw1 小时前
CSS学习记录20
前端·css·笔记·学习
界面开发小八哥2 小时前
「Java EE开发指南」如何用MyEclipse构建一个Web项目?(一)
java·前端·ide·java-ee·myeclipse
米奇妙妙wuu2 小时前
react使用sse流实现chat大模型问答,补充css样式
前端·css·react.js
傻小胖2 小时前
React 生命周期完整指南
前端·react.js
梦境之冢2 小时前
axios 常见的content-type、responseType有哪些?
前端·javascript·http