前端缓存的一些认识

前言

本文主要内容为我对前端缓存的一些看法,和一些服务器配置的运用。相信大家都有了解过雅虎的35条前端优化法则吧,前端缓存也是前端优化当中的必不可少的一部分,雅虎推荐为”Add an Expires or a Cache-Control Header”,可是对这2个http header 我们又知道多少呢。

#expires

HTTP 1.0 的header,nginx对expires有以下的一些配置:

1
2
3
4
5
6
7
8
9
expires 24h;
expires modified +24h;
expires @24h;
expires 0;
expires -1;
#Thu, 01 Jan 1970 00:00:01 GMT
expires epoch;
expires $expires;
add_header Cache-Control private;

当我们对服务器资源设置expires时,就会告诉浏览器(或代理)这个资源我们要多久到期,如下图的响应头
响应头
这时浏览器就会在下次请求该资源时,首先会判断是否在有效期内:是,就直接从本地缓存读取;否,请求头中携带if-modified-since,这个请求头的值就是上次响应头中的的last-modified,这时服务器会与当前资源的修改时间进行比较,看看last-modified是否在修改时间之前:是,响应304 not modified,浏览器就会从本地读取,而不需要再次下载资源了;否,就说明服务器资源变更过,返回200,body中为此资源内容,浏览器需要重新下载。这就是完整的缓存策略。


#cache-control

HTTP1.1 定义的规则
与expires类似,其对应关系为

1
2
3
expires --- cache-control
last-modified --- etag
if-modified-since --- if-match

功能类似,取值稍有不同

客户端(或代理)请求指令

1
2
3
4
5
6
7
Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>] //表明客户端愿意接收一个已经过期的资源。 可选的设置一个时间(单位秒),表示响应不能超过的过时时间。
Cache-Control: min-fresh=<seconds> //表示客户端希望在指定的时间内获取最新的响应。
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: only-if-cached //表明如果缓存存在,只使用缓存,无论原始服务器数据是否有更新。

服务器响应指令

1
2
3
4
5
6
7
8
9
Cache-control: must-revalidate //缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。
Cache-control: no-cache //强制所有缓存了该响应的缓存用户,在使用已存储的缓存数据前,发送带验证器的请求到原始服务器
Cache-control: no-store
Cache-control: no-transform
Cache-control: public //表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。
Cache-control: private //表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds> //设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。
Cache-control: s-maxage=<seconds> //覆盖max-age 或者 Expires 头,但是仅适用于共享缓存(比如各个代理),并且私有缓存中它被忽略。

那么no-cache 和 no-store 有什么关系呢?

相同点:
客户端每次请求都会与服务器建立连接
不同点:
no-cache,客户端会缓存资源,再次请求时会与对原始服务器上的资源进行验证,未更改->304,已更改->200;
no-store,客户端不会缓存资源,每次请求都重新下载原始服务器资源,对应响应状态码 200