使用 nginx 服务器支持 js/css/image 降级

使用 nginx 服务器支持 js/css/image 降级

我有一个需求,需要支持服务器代码的降级。

我的 nginx 配置文件中有以下行,表明浏览器可以缓存页面,但必须与服务器验证以检查文件是否发生变化。

add_header Cache-Control "no-cache";

对于我而言,此设置运行良好,并且我的服务器代码已完成所有升级。

但是当将资源降级为旧版本时,当浏览器尝试验证资源更改时,nginx 会表示资源没有改变,因此浏览器会显示缓存的(较新的)资源而不是降级的(较旧的)资源。

作为一种解决方法,我可以使用以下设置来完全禁用缓存,但它效率不高,而且我希望有缓存。

add_header Cache-Control "no-store";

那么我该如何让 nginx 识别降级呢?

答案1

在无缓存的情况下,浏览器通常会在 GET 请求中发出 If-Modified-Since 标头,以查看相关文件是否已从缓存副本发生变化。

服务器将会:

  1. 返回 304 - 未修改响应
  2. 返回另一个代码:
    • 200 - 如果服务器上的修改日期晚于标头传递的日期,则为 OK
    • 其他 - 可能返回的任何其他代码(4xx、5xx 等)

Nginx 将使用它所服务的文件上的修改时间戳来生成 Last Modified 标头并与 If-Modified-Since 进行比较。

因此,更新文件的时间戳touch /path/to/myfile.ext将导致 nginx 将其识别为在 If-Modified-Since 日期之后被修改,并允许 nginx 提供该文件。

或者,您应该能够通过在 nginx 配置中明确指定“Last Modified”标头来强制重新获取,该标头晚于 If-Modified-Since 的预期日期。在您的场景中,这基本上需要:

  1. 降级您的代码
  2. 使用当前日期修改 nginx 配置(例如):add_header Last-Modified Mon, 09 Jan 2012 17:07:00 GMT
  3. 重新加载 nginx

需要注意的一点是,如果您的静态资产在此之后发生变化,则硬编码标头将不会反映该变化(即,即使您“升级”代码,您仍然必须手动更改配置。

答案2

首先,“no-cache”在实践中并不一定意味着你认为的那样。我怀疑你真的想使用“Cache-Control: max-age=0, must-revalidate”。有些浏览器(Firefox)错误地将“no-cache”视为“no-store”的等价物,并且根本不在磁盘上缓存任何内容。它们只是在每次加载页面时从源重新获取所有内容,这严重浪费带宽,并且会降低用户体验。

其次,你的具体用例正是ETags是专为缓存而设计的,而不是在没有它们的情况下使用的简单的只进日期逻辑。(整个链接站点都是关于缓存的精彩读物,而不仅仅是关于电子标签)。

最后,您应该考虑使用某种形式的日期标识符(或更好的内容哈希)来命名您的资源,这样您就不必担心这种事情了。然后,您可以将缓存控制设置为 1 年。这需要更改工作流程并构建脚本,以便许多网站重命名文件并替换链接。但这就是 Google 和其他大公司所做的……

相关内容