Web缓存:
数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存
浏览器缓存:
HTTP 缓存、indexDB、cookie、localstorage 等等
HTTP缓存
- 强制缓存的优先级高于协商缓存
- 强缓存:命中缓存不需要和服务器端发生交互
- 协商缓存:不管是否命中都要和服务器端发生交互
- 流程:
强缓存
-
Expires
- 定义:缓存过期的时间,超过了这个时间点就代表资源过期
- 缺点:服务器时间,客户端时间可随意修改
- HTTP/1.0 的标准
-
Cache-Control
-
由多个字段组合而成
- max-age 指定一个时间长度,在这个时间段内缓存是有效的,单位是s(相对时间)
- no-store 禁止缓存,每次请求都要向服务器重新获取数据
- no-cache : max-age = 0仍然缓存,但是走协商缓存
- public 表明响应可以被任何对象(发送请求的客户端、代理服务器等等)Public 设置我们可以将 Http 响应数据存储到本地,但此时并不意味着后续浏览器会直接从缓存中读取数据并使用- 无法确定本地缓存的数据是否可用(可能已经失效)需要配合使用
- private 表明响应只能被单个用户(可能是操作系统用户、浏览器用户)缓存,是非共享的,不能被代理服务器缓存
- 缓存数据标记为已过期只是告诉客户端不能再直接从本地读取缓存了,还可能被再次用到(协商缓存)
- cache-control使用
-
- Cache-Control 的优先级更高,覆盖expire
协商缓存
浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。如果返回 304 Not Modified,代表资源没有发生改变可以使用缓存的数据,获取新的过期时间。反之返回 200 就相当于重新请求了一遍资源并替换旧资源
-
Last-modified(响应头)/If-Modified-Since(请求头)
- 服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304
- 注意: Last-modified 要记得配合 Expires/Cache-Control 使用,不设置,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样(根据响应头中2个时间字段 Date 和 Last-Modified 之间的时间差值,取其值的10%作为缓存时间周期。)
-
Etag/If-None-Match:
- 由服务器端上生成的一段 hash 字符串,第一次请求时响应头带上 ETag: abcd,之后的请求中带上 If-None-Match: abcd,服务器检查 ETag,返回 304 或 200
-
last-modified 和 Etag 区别
- 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新。
- Last-modified 只能精确到秒。
- 一些资源的最后修改时间改变了,但是内容没改变,使用 Last-modified 看不出内容没有改变。
- Etag 的精度比 Last-modified 高,属于强验证,要求资源字节级别的一致,优先级高。如果服务器端有提供 ETag 的话,必须先对 ETag 进行 Conditional Request
- Etag的值是需要服务器计算的且计算复杂,会消耗性能,视具体情况而定
实际使用
考虑缓存的内容:
- css样式文件
- js文件
- logo、图标
- html文件
- 可以下载的内容
一些不应该被缓存的内容:
- 业务敏感的 GET 请求
不经常改变的文件
- 给 max-age 设置一个较大的值,一般设置 max-age=31536000(一年)
- 文件名称添加版本号、hash 值
可能经常需要变动的文件:
- Cache-Control: no-cache / max-age=0
浏览器几种刷新方式对缓存的影响
1、在URI输入栏中输入然后回车
200 OK (from cache)
,浏览器发现该资源已经缓存了而且没有过期(通过Expires头部或者Cache-Control头部),没有跟服务器确认,而是直接使用了浏览器缓存的内容。其中响应内容和之前的响应内容一模一样
2、F5/点击工具栏中的刷新按钮/右键菜单重新加载
无论如何都发一个HTTP Request给Server,即使先前的响应中有Expires头部
Cache-Control: max-age=0 // Chrome强制加上的
If-Modified-Since: Fri, 15 Jul 2016 04:11:51 GMT
3、Ctl+F5
彻底的从Server拿一份新的资源过来
还需要添加一些HTTP Headers。按照HTTP/1.1协议,Cache不光只是存在Browser终端,从Browser到Server之间的中间节点(比如Proxy)也可能扮演Cache的作用
在Chrome 51 中会包含两个头部信息, 作用就是让中间的Cache对这个请求失效,这样返回的绝对是新鲜的资源。
Cache-Control: no-cache
Pragma: no-cache
Cache-Control: no-cache
总结
- 四种缓存的优先级:cache-control > expires > etag > last-modified**
- cache-control:设置过期的时间长度(秒),在这个时间范围内,浏览器请求都会直接读缓存
- expires:在 http 头中设置一个过期时间,在这个过期时间之前,浏览器的请求都不会发出,而是自动从缓存中读取文件,除非缓存被清空,或者强制刷新
- etag / if-none-match:服务器端返回资源时,如果头部带上了
etag
,那么资源下次请求时就会把值加入到请求头if-none-match
中 - last-modified / if-modified-since:服务器端返回资源时,如果头部带上了
last-modified
,那么资源下次请求时就会把值加入到请求头if-modified-since
中
补充:协商缓存在node的实现
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。