如何在 Ubuntu 16.04 上使用 Nginx 的 Header 模块配置浏览器缓存

如何在 Ubuntu 16.04 上使用 Nginx 的 Header 模块配置浏览器缓存
如何在 Ubuntu 16.04 上使用 Nginx 的 Header 模块配置浏览器缓存

介绍

网站加载速度越快,用户继续访问网站内容的可能性就越大。当网站图片较多,并且需要加载交互式脚本内容时,快速打开网站可真不是一项简单的任务,因为每一次的访问请求都要从服务器加载许多不同的文件。最大限度地减少请求的数量是提升网站访问速度的一种方法。

要实现减少请求数量的目的,有很多种方式,其中很重要的就是配置浏览器缓存。这样就可以告诉浏览器某些文件可以从本地缓存中取用,而不是每次访问都要向服务器重新请求。为此,我们必须引入新的 HTTP 响应标头,告诉浏览器如何操作。

这时我们就要用到 Nginx 的标头模块了,该模块可以向响应添加任意标头,但其主要作用是正确设置缓存标头。在本教程中,我们将看看如何使用 Nginx 的 header 模块来实现浏览器缓存。

准备工作

要学习本教程,您需要:

  • 使用此初始服务器设置教程设置的一台 Ubuntu 16.04 服务器,包括拥有 sudo 权限的非 root 用户。
  • 已经在 Ubuntu 16.04 上安装 Nginx 。

除了 header 模块,我们还将在本文中使用 Nginx 的 map 模块。

步骤 1 — 创建测试文件

在这一步中,我们将在默认的 Nginx 目录中创建几个测试文件。稍后我们将使用这些文件来检查 Nginx 的默认行为,然后测试浏览器缓存是否正常工作。

要确定通过网络提供什么样的文件,Nginx 不会分析文件内容,因为这个过程将非常缓慢,它只是查找文件扩展名以确定文件的MIME 类型,以确定文件的用途。

因此,我们测试文件的内容是无关紧要的。通过适当地命名文件,我们就可以让 Nginx 明白,一个空的文件可以是一个图像,而另一个是样式表。

使用 truncate 在默认 Nginx 目录中创建一个名为 test.html的文件。它的扩展名表示它是一个 HTML 文件。

sudo truncate -s 1k /var/www/html/test.html

我们以相同的方式再创建另外几个测试文件:一个jpg图像文件、一个css样式表文件和一个js JavaScript 文件。

sudo truncate -s 1k /var/www/html/test.jpg
sudo truncate -s 1k /var/www/html/test.css
sudo truncate -s 1k /var/www/html/test.js

下一步我们来测试 Nginx 如何发送缓存控制标头。

第 2 步 – 检查默认行为

默认情况下,所有文件都将具有相同的缓存行为。为了证明这一点,我们将使用我们在步骤 1 中创建的 HTML 文件。

因此,让我们检查是否 test.html 被提供浏览器应缓存响应时间的信息。以下命令可以从本地 Nginx 服务器请求文件并显示响应标头。

curl -I http://localhost/test.html

应该会看到以下几个 HTTP 响应标头:

Output: Nginx response headersHTTP/1.1 200 OK
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 10 Sep 2016 13:12:26 GMT
Content-Type: text/html
Content-Length: 1024
Last-Modified: Sat, 10 Sep 2016 13:11:33 GMT
Connection: keep-alive
ETag: "57d40685-400"
Accept-Ranges: bytes

在倒数第二行,可以看到 ETag 标签,其中包含所请求文件的唯一标识符。如果 curl重复执行前面的命令,将会看到完全相同的 ETag 值。

在使用浏览器访问网页时,当浏览器想再次请求相同的文件时(例如,刷新页面时),该 ETag 值将被存储并与If-None-Match 请求标头一起发送回服务器。

我们可以使用以下命令模拟这一点。确保更改 ETag 此命令中的 ETag 值以匹配先前输出中的值。

curl -I -H 'If-None-Match: "57d40685-400"' http://localhost/test.html

现在的响应将有所不同:

Output: Nginx response headersHTTP/1.1 304 Not Modified
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 10 Sep 2016 13:20:31 GMT
Last-Modified: Sat, 10 Sep 2016 13:11:33 GMT
Connection: keep-alive
ETag: "57d40685-400"

这一次,Nginx 将响应304 Not Modified。这一次它不会重新从服务器请求该文件,而是告诉浏览器加载本地的浏览器缓存文件。

通过这种方式,就可以减少重复加载网络文件,但它仍然不足以实现良好的缓存性能。ETag 的问题在于浏览器仍然会向服务器发送请求,询问它是否可以使用缓存文件。即使服务器以 304 响应而不是重新传输文件,但是发出请求并接收响应仍然需要一定的时间。

在下一步中,我们会使用 headers 模块来附加缓存控制信息。这样就可以使浏览器在本地缓存一些文件,而无需询问服务器是否可以这样做。

第 3 步 – 配置缓存控制和过期标头

除了 ETag 文件验证标头之外,还有两个缓存控制响应标头:Cache-ControlExpires。如果想要更好地控制缓存行为,使用 Cache-ControlExpires 具有更多选项并且更有用。

如果设置了这些标头,就可以告诉浏览器所请求的文件可以在本地保留一段时间(也可以永远)而无需再次请求。如果未设置标头,浏览器将始终会从服务器请求文件,获得 200 OK304 Not Modified 响应。

我们可以使用 header 模块来设置这些 HTTP 标头。header 模块是 Nginx 的核心模块,因此它不需要单独安装即可使用。

要添加头模块,请打开默认的 Nginx 配置文件。

sudo nano /etc/nginx/sites-available/default

找到 server 配置块,如下所示:

/etc/nginx/sites-available/default

. . .
# Default server configuration
#

server {
    listen 80 default_server;
    listen [::]:80 default_server;

. . .

在此处添加以下两个新部分:一个在 server 块之前,用于定义不同类型文件的缓存时长,另一个在块内,用于设置缓存头。

修改 /etc/nginx/sites-available/default

. . .
# Default server configuration
#

# Expires map
map $sent_http_content_type $expires {
    default                    off;
    text/html                  epoch;
    text/css                   max;
    application/javascript     max;
    ~image/                    max;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    expires $expires;
. . .

server 块之前的部分是一个新的 map 块,它定义了文件类型和该类型文件应缓存多长时间。

我们在这张地图中使用了几种不同的设置:

  • default 值设置为 off,这不会添加任何缓存控制标头。
  • 对于 text/html,我们将值设置为 epoch。这是一个特殊的值,它设置该类型文件没有被缓存,这会强制浏览器始终请求最新的内容。
  • 对于 text/cssapplication/javascript,它们是样式表和 Javascript 文件,我们将值设置为 max。这意味着浏览器将尽可能长时间地缓存这些文件,考虑到这些文件通常很多,从而大大减少了请求量。
  • 最后一个设置是 ~image/,它是一个正则表达式,将匹配包含 image/在其 MIME 类型名称中的所有文件类型(如image/jpgimage/png)。像样式表一样,网站上通常有很多可以安全缓存的图像,因此我们也将其设置 max为。

在 server 块中,expires 指令(headers 模块的一部分)设置缓存控制头。它使用 $expires 变量来设置。这样,生成的 header 将因文件类型而异。

保存并关闭文件以退出。

要启用新配置,请重新启动 Nginx。

sudo systemctl restart nginx

接下来,让我们确保我们的新配置有效。

第 4 步 – 测试浏览器缓存

对用于测试的 HTML 文件执行与之前相同的请求。

curl -I http://localhost/test.html

这一次的返回的内容会有所不同。应该会看到两个额外的 HTTP 响应标头:

Nginx 响应头

HTTP/1.1 200 OK
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 10 Sep 2016 13:48:53 GMT
Content-Type: text/html
Content-Length: 1024
Last-Modified: Sat, 10 Sep 2016 13:11:33 GMT
Connection: keep-alive
ETag: "57d40685-400"
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Cache-Control: no-cache
Accept-Ranges: bytes

Expires 标签显示一个过去的日期,而 Cache-Control被设定为 no-cache,它告诉浏览器总是问服务器是否有该文件的较新版本(用ETag头,像以前一样)。

而在测试图像文件的时候,会获得不同的相应。

curl -I http://localhost/test.jpg

 Nginx 响应头

HTTP/1.1 200 OK
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 10 Sep 2016 13:50:41 GMT
Content-Type: image/jpeg
Content-Length: 1024
Last-Modified: Sat, 10 Sep 2016 13:11:36 GMT
Connection: keep-alive
ETag: "57d40688-400"
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Accept-Ranges: bytes

在这种情况下,Expires 会显示一个很久以后的日期,而 Cache-Control 的值为 max-age ,告诉浏览器它可以缓存该文件多长时间。这告诉浏览器尽可能长时间地缓存该图像,因此该图像的任何后续出现都将使用本地缓存,并且根本不会向服务器发送请求。

如果测试 test.jstest.css 文件,结果应该与该图片文件类似。

这意味着我们已经正确配置了缓存控制标头,通过这样的配置,我们的网站会减少服务器请求,并获得一定的性能提升。

结论

headers 模块可用于向响应添加任何任意标头,但适当设置缓存控制标头是其最有用的应用之一。它提高了网站用户的访问体验,尤其是在延迟较高的网络上。

原创文章,作者:牛奇网,如若转载,请注明出处:https://www.niuqi360.com/website-front-end/ubuntu-16-04-nginx-header/

发表评论

登录后才能评论