前言
强缓存: 浏览器不会向服务器发送任何请求,直接从本地缓存中读取文件并返回 Status Code: 200 OK。常见如下:
Status Code: 200 OK (from memory cache) // 内存缓存
Status Code: 200 OK (from disk cache) // 磁盘缓存
读取本地的缓存有from memory cache和from disk cache的区别:
这是浏览器的缓存策略。一般memory cache一般存放比较小的文件,disk cache一般存放比较大的文件。
协商缓存: 向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存。如果命中,则返回304状态码,并带上新的response header通知浏览器从缓存中读取资源。
在Response Headers中展示如下图:
工作流程
- 浏览器在加载资源时,根据请求头的
expires和cache-control判断是否命中强缓存,若命中则直接从缓存读取资源,不会发请求到服务器,Status Code显示为200 OK (from memory cache)或200 OK (from disk cache) - 如果没有命中强缓存,则浏览器会发送一个请求到服务器,通过
Etag和last-modified验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,状态码为304 Not Modified,但是不会返回这个资源的数据,浏览器则依然是从缓存中读取资源 - 如果前面两个都没有命中,则直接从服务器加载资源,并返回状态码
200
详细说明
1. expires和cache-control
首先cache-control的优先级高于expires。cache-control在HTTP/ 1.1中出现,表示的是相对时间。而Expires在HTTP/ 1.0中出现,标识一个资源过期时间,是一个绝对时间,由服务器返回,但由于Expires 受限于本地时间,如果修改了本地时间,则可能会造成缓存失效,因此Expires有这样的bug存在。
HTTP HEADER中常见返回值:
Expires: Wed, 15 Apr 2020 01:09:53 GMT
Cache-Control: max-age=86400
Cache-Control: no-cache // 可以存储在本地缓存区中,只是在于原始服务器进行新鲜度验证之前,缓存不能将其提供给客户端使用
Cache-Control: no-store // 真正的不缓存数据到本地
Cache-Control: public // 以被所有用户缓存(多用户共享),包括终端和CDN等中间代理服务器
Cache-Control: private // 只能被终端浏览器缓存(而且是私有缓存),不允许中继缓存服务器进行缓存
2. ETag、If-None-Match
ETag和If-None-Match是组合来使用的。Etag就像一个指纹,资源变化都会导致ETag变化,跟最后修改时间没有关系,因此,ETag可以保证每一个资源是唯一的。If-None-Match的header会将上次返回的Etag发送给服务器,询问该资源的Etag是否有更新,有变动就会发送新的资源回来。
ETag的优先级比Last-Modified更高
参考文档: ETag
浏览器在请求时在Request Headers中携带内容如下:
If-None-Match: W/"5exxxd45-9xx"
If-None-Match的值为上次返回的Etag
如果资源未改变,返回状态码如下:
Status Code: 304 Not Modified
3. Last-Modified、If-Modified-Since
Last-Modified 表示本地文件最后修改日期,浏览器会在request header加上If-Modified-Since(上次返回的Last-Modified的值),如下图所示,询问服务器在该日期后资源是否有更新,如果有更新的话就会将新的资源发送回来。但是如果在本地打开缓存文件,就会造成Last-Modified被修改,所以在HTTP/1.1出现了ETag
If-Modified-Since: Fri, 10 Apr 2020 14:05:57 GMT
缓存的选择
协商缓存需要配合强缓存使用,如果不启用强缓存的话,协商缓存根本没有意义。
大部分web服务器都默认开启协商缓存,而且是同时启用【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】。Etag等一般是在nginx中配置完成的。
希望对你能有所帮助!