http的缓存可以减少对服务器端的请求,将之前获得的资源信息重复利用。
1、通过ETag验证缓存的响应
服务器端使用ETag HTTP标头传递验证令牌
验证令牌可以实现高效的资源更新检查,资源未发生变化时不会传送任何数据。
示例:
假定在首次获取资源120秒后,浏览器又对该资源发起了新的请求。
首先,浏览器会检查本地缓存并找到之前的响应。
若未过期,返回该缓存信息。
若过期,浏览器重新对该资源发起请求,如果不适应验证令牌,浏览器会重新发起新的请求并获取完整响应,此时若资源并未发生变化,那么重新下载的信息与缓存的信息完全一致,这样的请求是对资源的一种浪费。
ETag,是服务器端生成并返回的随机令牌,通常是文件内容的哈希值或者某个其他指纹,客户端只需要在下次请求时将其发送至服务器,如果指纹相同则表示资源未发生变化,此时可跳过下载。

如图所示,客户端自动在'IF-None-Match' HTTP请求头内提供ETag令牌。服务器根据当前资源核对令牌。如果未发生变化,服务器端返回‘304 Not Modified’响应,告知浏览器缓存中的响应未发生变化,可以再沿用120秒。
浏览器会完成几乎所有工作。开发者需要做的就是确保服务器提供必要的ETag令牌,检查服务器文档中有无必要的配置标志。HTML5 Boilerplate 项目包含所有最流行服务器的配置文件样例,其中为每个配置标志和设置都提供了详细的注解。在列表中找到您喜爱的服务器,查找合适的设置,然后复制/确认您的服务器配置了推荐的设置。
2、Cache-Control
每个资源都可以通过Cache-Controller HTTP头定义其缓存策略
Cache-Control指令控制谁在什么条件下可以缓存响应以及可以缓存多久。
从性能优化角度来说,最佳请求时无需与服务器通信的请求,可以通过响应的本地副本消除所有网络延迟,以及避免数据传送的流量费用。
Cache-Control是在HTTP/1.1规范中定义的,取代了之前用来定义响应缓存策咯的标头,所有浏览器都支持Cache-Control。
(1)no-cache与no-store
no-cache:
表示必须先与服务器确认返回的响应是否发生了变化,然后才能使用该响应来满足后续对同一网址的请求。因此,如果存在合适的验证令牌(ETag),no-cache会发起往返通信来验证缓存的响应,如果资源未发生变化,则可避免下载。
no-store:
禁止浏览器以及所有中间件缓存存储任何版本的返回响应,每次用户请求该资产时,都会向服务器发送请求并下载完整响应。
(2)public与private
public:
如果响应被标记为public,即使它有关联的HTTP身份验证,也可以缓存响应。大多是情况下,public非必需。
private:
private响应可以缓存,通常只为单个用户缓存,不允许任何中间缓存对其进行缓存。比如用户浏览器可以缓存包含用户私人信息的HTML网页,但是CDN却不能缓存。
(3)max-age
指定请求的开始时间,允许获取的响应被重用的最长时间(S);
3、定义最佳Cache-Control策略

按照以上决策树为应用使用的特定资源或一组资源确定最佳缓存策略,在理想的情况下,开发者的目标应该是在客户端上缓存尽可能多的响应,缓存尽可能长的时间,并为每个响应提供验证令牌,以实现高效的重新验证。
4、废弃和更新缓存的响应
在资源过期之前,将一直使用本地缓存的响应。
可以通过在网址中嵌入文件内容指纹,强制客户端更新到最新版本的响应。
未获得最大性能,每个应用都需要定义自己的缓存层次结构。
浏览器发出的所有HTTP请求会首先路由到浏览器缓存,已确认是否缓存了可用于满足请求的有效响应。如果有匹配的响应,则从缓存中读取响应,避免网络延迟和传送产生的流量费用。
如果想更新或者废弃缓存的响应,该怎么办?浏览器缓存响应之后,缓存的版本将一直使用到过期或者使用到某种原因从缓存中删除。
此时要更新缓存,通常情况下可以通过在文件名中嵌入文件的指纹或版本号来实现。
缓存策略:较长的过期时间、控制可以缓存响应的位置以及随需的更新。

缓存层次结构-可以控制每个响应的缓存时间还可以控制访问者看到新版本的速度。定义每个资源的缓存策略。
HTML-no-cache,浏览器在每次请求时始终重新验证文档,并在内容变化时获取最新版本信息。在HTML文档内,CSS与JavaScript的网址中会嵌入指纹,如果这些文件发生变化网页的HTML也会随之改变,并会下载HTML响应的副本。
允许浏览器中间缓存CSS,并将CSS设置为1年后到期。因为嵌入指纹信息,可以放心的使用这样的远期过期。
JavaScript也是设置为一年后到期,但是标记为private,不允许中间缓存。
图像缓存时不包含版本或惟一指纹,并设置为一天后到期。
5、缓存检查清单
不存在最佳缓存策略。这需要根据通信模式、提供的数据类型以及应用特定数据更新要求,为每个资源定义和配置合适的设置,以及整体的缓存层次结构。
制定缓存策略时,需要牢记的技巧和方法:
使用一致的网址:网址区分大小写。如果在不同的网址上提供相同的内容,将会多次获取和存储这些内容。
确保服务器提供验证令牌(ETag):有了验证令牌,当服务器上的资源未发生变化是,就不需要传送相同的字节。
确定中间缓存可以缓存哪些资源:对所有用户的响应完全相同的资源非常适合由CDN以及其他中间缓存进行缓存。
为每个缓存确定最佳缓存周期:不同资源可能有不同的更新要求。为每个资源审核并确定合适的max-age。
确定最适合自己网站的缓存层次结构:可以通过HTML文档组合使用包含内容指纹的资源网址和短时间或no-cache周期,来控制客户端的更新速度。
最大限度减少搅动:某些资源的更新比其他资源频繁。如果资源的特定部分(例如 JavaScript 函数或 CSS 样式集)会经常更新,可以考虑将其代码作为单独的文件提供。这样一来,每次获取更新时,其余内容(例如变化不是很频繁的内容库代码)可以从缓存获取,从而最大限度减少下载的内容大小。
参考网址:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn
(请自备翻墙技能:)
配置样例链接:https://github.com/h5bp/server-configs




