强制缓存和协商缓存是 HTTP 缓存机制中的两种不同策略,用于控制客户端(浏览器)是否向服务器发送请求来获取资源的更新版本。这两种缓存策略可以通过设置响应头信息来实现。
强制缓存是利用客户端本地的缓存来直接返回资源,而不必发起请求到服务器。在强制缓存有效期内,客户端会直接从本地缓存中加载资源,不会发起请求到服务器。通常通过在响应头中设置 Cache-Control: max-age=seconds
或 Expires: datetime
来控制资源的强制缓存有效期,让客户端在有效期内不发起请求,直接使用缓存。
强制缓存缓存需要服务端配置,以下是使用nginx配置的例子
Cache-Control 头告诉浏览器资源的最大缓存时间为多少秒。在 Nginx 中,可以通过add_header Cache-Control来配置
location ~* \.(html|css|js|png|jpg)$ {
// 设置资源的最大缓存时间为3600秒(1小时)
add_header Cache-Control "max-age=3600, public";
}
location ~* \.(html|css|js|png|jpg)$ {
// 如果不想让代理或浏览器缓存,加 no-cache 参数
Cache-Control: no-cache;
}
这样浏览器 F5 刷新时,nginx 静态资源缓存 设置返回的状态码就是 http 200,而不是 http 304
Expires 头告诉浏览器在多长时间内缓存资源。在 Nginx 中,可以通过 expires 指令来配置 Expires 头。
location ~* \.(html|css|js|png|jpg)$ {
expires: 3d; // 缓存3天
}
除以上值外,还有以下值可以设置
expires 3d; // 表示缓存 3 天
expires 3h; // 表示缓存 3 小时
expires 3y; // 表示缓存 1 年
expires max; // 表示缓存 10 年
expires -1; // 表示永远过期。
当资源的强制缓存过期或客户端首次请求资源时,客户端会向服务器发送请求,服务器会判断资源是否发生更新。如果资源没有变化,服务器会返回 304 Not Modified 状态码,并通过响应头中的 Last-Modified 或 ETag 与客户端缓存的值进行比较,告知客户端直接使用缓存。这种方式称为协商缓存,因为客户端和服务器需要就缓存资源的新鲜度进行协商。
Last-Modified 是指资源的最后修改时间,在 Nginx 中可以通过 add_header Last-Modified 来配置。
location ~* \.(html|css|js)$ {
add_header Last-Modified $date_gmt;
}
ETag 是一个由服务器生成的唯一标识符,用于标志资源变化。在 Nginx 中,可以通过 etag 指令来配置 ETag
location ~* \.(html|css|js)$ {
etag on;
}
以上配置开启了对所有的 html、css 和 js 文件的 ETag 功能。
总结起来,强制缓存利用客户端的本地缓存来直接返回资源,减少了对服务器的请求,适用于资源不经常变化的情况;而协商缓存在资源需要更新时,通过与服务器协商来确定是否使用缓存,适用于资源可能频繁变化的情况。