为常见的内容类型设置 Nginx 和 Apache 缓存控制标头

介绍

Cache-Control 是 HTTP 缓存标头,其中包含用于缓存请求和响应的指令。它用于定义资源的缓存方式、缓存位置以及到期前的最长期限。当您访问网站时,浏览器会将图像和网站数据保存在被称为缓存的本地存储中。当您再次访问同一个网站时,Cache-Control 设置规则,以确定是从本地缓存加载,还是浏览器应向服务器发送请求以获取新资源。

为常见的内容类型设置 Nginx 和 Apache 缓存控制标头
为常见的内容类型设置 Nginx 和 Apache 缓存控制标头

为了更好地理解浏览器如何使用缓存,还需要了解浏览器缓存和 HTTP 标头。

什么是浏览器缓存?

浏览器缓存是临时将 Web 文档(例如图像、媒体和页面等)存储于本地。这可以减少服务器带宽的占用,提高用户端的加载速度。浏览器只会在被称为 TTL 的特定时间段内保存这些资源。一旦 TTL 过期,浏览器将向服务器发送请求以下载最新资源。

什么是 HTTP 标头?

HTTP header 是 HTTP 请求和响应的核心部分,并提供有关请求或响应的所需信息。所有的 header 都不区分大小写,header 字段由冒号分隔。这些标头包含有关每次通信的信息。例如,请求头包含有关请求的资源、客户端使用的浏览器以及客户端将接受的数据格式等信息。响应标头包含有关请求是否成功完成以及响应正文中任何资源的语言和格式的信息。

缓存控制头被分解为指令。您可以使用以下命令查看https://google.com的缓存控制标头:

curl -I https://google.com

你应该得到以下输出:

HTTP/1.1 301 Moved Permanently
 Location: https://www.google.com/
 Content-Type: text/html; charset=UTF-8
 Date: Fri, 05 Jun 2020 03:03:10 GMT
 Expires: Sun, 05 Jul 2020 03:03:10 GMT
 Cache-Control: public, max-age=2592000
 Server: gws
 Content-Length: 220
 X-XSS-Protection: 0
 X-Frame-Options: SAMEORIGIN
 Alt-Svc: h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"

可以看到,冒号左边是 cache-control,冒号的右边为设置的值,可以有一个或几个逗号分隔的缓存控制值。这些值被称为指令,它们指示谁可以缓存资源,以及这些资源在必须更新之前可以缓存多长时间。

最常见的缓存控制标头详述如下:

Cache-Control: Public

该指令指示响应可以由任何缓存存储,即使响应通常是不可缓存的。

Cache-Control: Private

该指令表示响应只能由访问文件的浏览器缓存。它不能被代理或 CDN 等缓存。

Cache-Control: Max-Age

该指令指示资源被视为可用数据的最长时间。换句话说,资源在下载后可以从缓存中保存多长时间。例如,如果 max age 设置为 3600 意味着返回的资源有效期为 3600 秒,之后浏览器必须请求更新的版本。

Cache-Control: No-Cache

该指令指示浏览器可以缓存资源,但必须首先向源服务器进行验证。

建议对 Html 文件类型使用 Cache-Control: no-cache 先验证服务器上的资源,然后再从缓存中读取。

Cache-Control: No-Store

该指令表示不应缓存资源,例如,您不希望将银行详细信息存储在任何浏览器缓存中。对于这些目的,可以使用 no-store。

为 Apache 和 Nginx Web 服务器配置 Cache-Contol 标头

在本节中,我们将向您展示如何在 Apache 和 Nginx 中设置 HTTP Cache-Control 标头。

Apache

对于 Apache Web 服务器,您需要编辑网站虚拟主机配置文件以实现 HTTP Cache-Control 标头,例如:

nano /etc/apache2/sites-enabled/niuqi360.conf

添加以下内容:

<filesMatch ".(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
    Header set Cache-Control "max-age=3600, public"
</filesMatch>

如果要为所有文件启用缓存控制,请在 filesMatch 块之外添加 Header 设置行。

如上所示,我们将 Cache-Control 标头的 max-age 值设置为 3600 秒,并将列出的文件设置为 public。

也可以在web 根目录下的任何目录中的 .htaccess 文件中进行设置。如果您使用的是 SSL,您应该考虑将其添加到您的虚拟主机配置的 ssl 版本中,该版本也位于/etc/apache2/sites-enabled/

nginx

对于 Nginx Web 服务器,您需要编辑您的网站虚拟主机配置文件,以实现 HTTP Cache-Control 标头,例如:

nano /etc/nginx/sites-enabled/ niuqi360

添加以下内容:

location ~* .(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$ {
     expires 1h;
     add_header Cache-Control "public, no-transform";
}

如果您想为所有文件启用缓存控制,请添加一个不包含位置块的 add_header 行,因为位置块的作用是指定您使用指令(ico、pdf、flv 等)定位的特定文件类型。

我们建议对所有可缓存资源进行以下设置:

  1. 对于 js、css 和图像文件,设置 Cache-Control: public, max-age=31536000, no Etag, no Last-Modified 设置。

    Apache:
<filesMatch ".(js|css|jpg|jpeg|png|gif|js|css|ico|swf)$">
                Header set Cache-Control "max-age=31536000, public"
                Header unset Last-Modified
                Header unset ETag
            </filesMatch>

nginx:

location ~* .(js|css|jpg|jpeg|png|gif|js|css|ico|swf)$ {
                expires 1y;
                etag off;
                if_modified_since off;
                add_header Cache-Control "public, no-transform";
            }
            

将 Last-Modified 日期设置为上次更改资源的时间。(注意:这在 Nginx 或 Apache 中默认已发生)
如果您需要精确控制资源何时失效,我们建议使用 URL 指纹或版本控制技术。
例如,当您对一个 css 文件进行更改时,您应该更改名称以确保更新的文件将被所有人看到,因为文件已被缓存。这称为 URL 指纹。

对于 html 文件,使用 Cache-Control:no-cache 和 Etag。

Apache:

<filesMatch ".(html$">
        Header set Cache-Control "no-cache"
    </filesMatch>

Nginx:

location ~* .(html)$ {
        etag on;
        add_header Cache-Control "no-cache";
    }

使用 Webpack、Gulp 或其他工具,并为您的 js、css 和图像文件添加唯一的哈希值。(例如,app-67ce7f3483.css)。这将强制浏览器下载所需文件的新版本。

以下图表可能有助于确定应将哪些特定缓存指令添加到资源中:

缓存图表.png

Etag(实体标签)

Etag 也称为 HTTP 响应头,是一种缓存验证器,用于确定浏览器缓存中的组件是否与源服务器上的组件匹配。这将有助于缩短加载时间,因为如果可以从本地缓存中检索资源,浏览器就不需要向服务器发出额外的请求。

ETag 标签是 HTTP 的一部分。它是 HTTP 为 Web 缓存验证提供的几种机制之一,它允许客户端发出条件请求。这让缓存更高效,并节省带宽,因为如果内容没有改变,Web 服务器就不需要重新发送资源。ETag 还可以用于优化并发控制。

ETag 是由 Web 服务器分配给返回资源的特定版本的标签。如果 URL 的资源内容发生变化,则会分配一个新的不同的 ETag。以这种方式使用的 ETag 类似于指纹,可以通过快速比较它们,以确定资源的两个版本是否相同。比较 ETag 只对一个 URL 链接有意义,因为从不同 URL 链接获取的资源的 ETag 可能相同,也可能不相同。

在 Nginx 或 Apache 中为资源配置 Etag

Etags 也称为实体标签,是处理 304 响应的另一种方式。304 响应是 Web 服务器告诉用户,本地缓存已经是最新版本,尽管缓存时间可能已经到期,但仍无需重新访问该文件。

它的工作方式是,当浏览器访问已经访问过的页面时,浏览器将向服务器发送验证信息,确认是使用本地缓存还是获取最新版本的资源。如果有更新的文件,Web 服务器会将该文件发送到浏览器,如果没有,则只告诉浏览器使用本地缓存文件。

Etags 具有以下优点:

  • 有效过滤。
  • 更快的加载时间。
  • 降低磁盘负载。
  • 较低的带宽使用率。

使用 ETag 的全部意义在于,它们旨在为我们提供关于文件是否已更改的更精确指示,而不仅仅是基于时间戳。Etag 的作用是告诉浏览器文件是否已更新,因此如果 Etag 不存在,浏览器将始终表现为文件已更改并且不会使用缓存。ETag 在单台服务器上比在负载均衡服务器上更好,因为如果 Etags 与其他服务器不匹配,用户将无法获得 Etag 的快速响应!

在 Apache 中配置 Etags

默认情况下,Apache Web 服务器中启用了 ETags。如果要检查是否启用了 ETags,请运行以下命令:

curl -I localhost

您应该在输出内容中看到 ETags 已启用:

HTTP/1.1 200 OK
Date: Wed, 01 Jul 2020 09:00:27 GMT
Server: Apache/2.4.7 (Ubuntu)
Last-Modified: Mon, 03 Feb 2020 14:55:14 GMT
ETag: "2cf6-59dad1c5a32cd"
Accept-Ranges: bytes
Content-Length: 11510
Vary: Accept-Encoding
Content-Type: text/html

您还可以在系统中完全禁用 ETag,并使用 cache control headers 来控制缓存。

您可以通过编辑 Apache 默认配置文件来禁用 ETag:

nano /etc/apache2/apache2.conf

在您的默认 Web 根目录部分中添加以下行:

Header unset Etag
FileETag none

保存并关闭文件,然后重新启动 Apache 服务以应用更改:

systemctl restart apache2

如果您无权访问服务器上的 SSH,则可以编辑 .htaccess 文件以禁用 ETag。

nano .htaccess

添加以下几行:

Header unset Etag
FileETag none

完成后保存并关闭文件。

您还可以使用以下命令验证 ETags 是否已禁用:

curl -I localhost

通过以下输出,可以看到已经禁用了Etags 标签:

HTTP/1.1 200 OK
Date: Wed, 01 Jul 2020 09:01:11 GMT
Server: Apache/2.4.7 (Ubuntu)
Last-Modified: Mon, 03 Feb 2020 14:55:14 GMT
Accept-Ranges: bytes
Content-Length: 11510
Vary: Accept-Encoding
Content-Type: text/html

在 Nginx 中配置 Etags

默认情况下,一旦设置了缓存头,Nginx 也会激活 Etags。要确定是否启用了 Etag,请运行以下命令:

curl -I localhost

您应该在以下输出中看到 ETags 已启用:

HTTP/1.1 200 OK
    Server: nginx
    Date: Thu, 10 Sep 2020 18:55:02 GMT
    Content-Type: application/octet-stream
    Content-Length: 1024
    Last-Modified: Thu, 10 Sep 2020 18:50:29 GMT
    Connection: keep-alive
    ETag: "5f5a7575-400"
    Expires: Thu, 10 Sep 2020 19:55:02 GMT
    Cache-Control: max-age=3600
    Cache-Control: public, no-transform
    Accept-Ranges: bytes 

也可以禁用 ETag,通过编辑 Nginx 默认配置文件来禁用 ETag:

nano /etc/nginx/sites-enabled/niuqi360

在配置文件中添加 etag off; :

location ~* .(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$ {
    expires 1h;
    etag off;
    add_header Cache-Control "public, no-transform";
}

保存并关闭文件,然后重新启动 nginx 服务以应用更改:

systemctl restart nginx

通过运行以下命令来检查 ETags 是否已成功禁用:

curl -I localhost

应该会返回如下内容,说明已经成功禁用 Etags 标签:

HTTP/1.1 200 OK
    Server: nginx
    Date: Thu, 10 Sep 2020 19:02:08 GMT
    Content-Type: application/octet-stream
    Content-Length: 1024
    Last-Modified: Thu, 10 Sep 2020 18:50:29 GMT
    Connection: keep-alive
    Expires: Thu, 10 Sep 2020 20:02:08 GMT
    Cache-Control: max-age=3600
    Cache-Control: public, no-transform
    Accept-Ranges: bytes    

安全标头

既然您已经阅读了有关缓存标头的所有内容,我们建议您查看我们的配套文章:如何在 Nginx 和 Apache 中配置安全标头

原创文章,作者:牛奇网,如若转载,请注明出处:https://www.niuqi360.com/%e4%bf%a1%e6%81%af%e5%ae%89%e5%85%a8/setting-cache-control-headers-in-nginx-and-apache/

发表评论

登录后才能评论