一个一般情况下的例子:
浏览器输入url,第一次发送http请求的时候,肯定是不会有缓存这一说的,直接从服务器读取数据。
以下讨论的是第二次以后的请求相同内容(js,css,图片等静态资源)的时候,缓存是如何工作的。
1、判断是否有强制缓存
第一次返回http响应的时候, 如果响应中携带cache-control
或者expires
,这两个字段,
则说明这个资源是设置了强制缓存,
什么意思呢,就是第二次请求这个资源时,在浏览器端,先去判断cache-control
或者expires
的值,
如果成立,则直接在缓存中获取,不去发送http请求,典型代表200 OK(from memory cache)
。
那么是怎么进行判断的呢,expires
是http1的标准,cache-control
是http1.1的标准。expires
指定资源的过期时间,浏览器第二次请求时,判断本地时间是否超过了这个过期时间,
如果没有超过,则直接从缓存中取数据,不去发送http请求到服务端,
如果超过过期时间,则发送http请求到服务端
cache-control
中有个max-age
指令,
和expires
的意思差不多,也是指定过期时间,
但是和expires
不同的是,max-age
指定的值,是个相对值,相对于第一次请求的时间,
也就是说浏览器第二次请求时,如果相对于第一次请求的时间,
没有超过max-age
指定的时间,则直接从缓存中取数据,不去发送http请求到服务端;
浏览器第二次请求时,如果相对于第一次请求的时间,
超过max-age
指定的时间,则需要发送http请求到服务端。
http响应中如果同时包括expires
和cache-control
,两个需要都满足,才会从缓存中获取资源。
实际中,用一个就可以,cache-control
的优先级高于expires
。expires
是个相对于服务器的绝对时间,如果把本机的时间修改了,和服务器不一致,则不准确了,推荐用cache-control
就可以。
2、判断是否有协商缓存
第一次返回http响应的时候, 如果响应中携带Etag
或者last-modified
,这两个字段,
则也说明服务器端也希望这个资源被缓存。
那么是怎么进行缓存操作的呢
强制缓存不成功,才去判断是否有协商缓存,此时需要发送http请求,
发送http请求时,如果第一次请求返回的响应中携带Etag
或者last-modified
,
则第二次请求头会包含if-none-match
或者if-modified-since
,
第一次请求返回的响应中Etag
指令是响应数据的一个hash值,
第二次请求时,会将这个hash值给到if-none-match
,
然后在服务器端,计算数据的hash值,得出一个hash,判断这个计算出的hash与if-none-match
的hash是否相等,
如果相等,则说明第二次请求的数据并没有发生变化,
服务器端会返回304响应状态码,告诉浏览器端,直接取浏览器端的缓存;
如果不相等,服务器端返回200,生成新的Etag
值,返回新数据,给到浏览器。
if-modified-since
的目的和Etag
的目的一样,他是个相对于服务器的绝对时间,
如果把本机的时间修改了,和服务器不一致,则不准确了,,如果把本机的时间修改了,则不准确了,推荐用Etag
就可以。
其他
以上是个正常流程,看一下其他的情况:
1、 第一次返回http响应的时候, cache-control
的max-age
为0或者no-cache,
就是服务器端不希望浏览器直接读取缓存,而是要通过发送http请求,通过Etag
或者last-modified
等指令去判断是否读取缓存。
这时候要么返回200
,要么返回304
,不会返回200 OK(from memory cache)
,
意思就是怎么都要去服务器端去判断一下内容有没有更新,不允许直接读取缓存,
2、 发送http请求的时候,如果带有cache-control
的max-age
为0,则为浏览器不去判断是否有缓存,直接发送http请求,
chrome刷新浏览器的时候,请求中会默认带上cache-control
的max-age
为0,
这种情况就不会返回200 OK(from memory cache)
。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。