前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在Ubuntu 16.04上使用Nginx的头模块实现浏览器缓存

如何在Ubuntu 16.04上使用Nginx的头模块实现浏览器缓存

原创
作者头像
小翼111
修改2018-09-27 16:10:15
1.3K0
修改2018-09-27 16:10:15
举报

介绍

网站加载得越快,访问者留下的可能性就越大。当网站充满了由后台加载的脚本运行的图像和交互式内容时,打开网站并不是一项简单的任务。它包括从服务器逐个请求许多不同的文件。最大限度地减少这些请求的数量是加快网站速度的一种方法。

这可以通过多种方式完成,但其中一个更重要的步骤是配置浏览器缓存。这告诉浏览器,一次下载的文件可以从本地副本重用,而不是一次又一次地请求服务器。为此,必须引入告知浏览器行为方式的新HTTP响应标头。

这就是Nginx的标题模块发挥作用的地方。此模块可用于向响应添加任意任意标头,但其主要作用是正确设置缓存标头。在本教程中,我们将了解如何使用Nginx的头模块来实现浏览器缓存。

准备

要学习本教程,您需要:

  • 一台已经设置好可以使用sudo权限的非root账号的Ubuntu 16.04服务器,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器
  • 在服务器上安装Nginx。

除了头模块,我们还将在本文中使用Nginx的地图模块。

第1步 - 创建测试文件

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

为了决定通过网络提供什么类型的文件,Nginx不分析文件内容; 那会非常慢。相反,它只是查找文件扩展名以确定文件的MIME类型,这表示文件的用途。

由于这种行为,我们的测试文件的内容是无关紧要的。通过适当地命名文件,我们可以欺骗Nginx,例如,一个完全空的文件是一个图像而另一个是样式表。

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

代码语言:javascript
复制
sudo truncate -s 1k /var/www/html/test.html

让我们以相同的方式创建一些测试文件:一个jpg图像文件,一个css样式表和一个jsJavaScript文件。

代码语言: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服务器请求文件并显示响应头。

代码语言:javascript
复制
curl -I http://localhost/test.html

您应该看到几个HTTP响应标头:

代码语言:javascript
复制
HTTP/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值。

使用Web浏览器时,如果浏览器想要再次请求相同的文件(例如,刷新页面时),ETag则会将值存储并发送回带有If-None-Match请求标头的服务器。

我们可以使用以下命令在命令行上模拟它。确保更改ETag命令中的值以匹配先前输出中的值ETag

代码语言:javascript
复制
curl -I -H 'If-None-Match: "57d40685-400"' http://localhost/test.html

现在的反应会有所不同:

代码语言:javascript
复制
HTTP/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-ControlExpiresCache-Control是更新的版本,它有比Expires更多的选项,如果你想更好地控制你的缓存行为通常更有用。

如果设置了这些标头,它们可以告诉浏览器所请求的文件可以在本地保存一段时间(包括永久)而无需再次请求它。如果未设置标头,浏览器将始终从服务器请求文件,期望200 OK304 Not Modified响应。

我们可以使用头模块来设置这些HTTP头。头模块是核心Nginx模块,这意味着它不需要单独安装即可使用。

要添加标题模块,请用您喜欢的文本编辑器中打开在nano中的默认的Nginx配置文件。

代码语言:javascript
复制
sudo nano /etc/nginx/sites-available/default

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

代码语言:javascript
复制
. . .
# Default server configuration
#
​
server {
    listen 80 default_server;
    listen [::]:80 default_server;
​
. . .

在此处添加以下两个新部分:一个在server块之前,用于定义缓存不同文件类型的时间长度,以及一个在其中的一个,以适当地设置缓存头。

代码语言:javascript
复制
. . .
# 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块,它定义了文件类型与缓存该类文件的时间之间的映射。

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

  • 默认值设置为off,不会添加任何缓存控件头。对于我们对缓存应该如何工作没有特别要求的内容,这是一个安全的选择。
  • 至于text/html,我们将值设置为epoch。这是一个特殊的值,它明确地没有缓存,这迫使浏览器始终询问网站本身是否是最新的。
  • 对于text/cssapplication/javascript,它们是样式表和Javascript文件,我们将值设置为max。这意味着浏览器将尽可能长时间地缓存这些文件,从而减少了大量请求,因为通常有很多这些文件。
  • 最后一项设置是~image/,这是一个正则表达式会匹配所有的文件类型(包括image/)在他们的MIME类型名称(如image/jpgimage/png)。与样式表一样,网站上通常有很多可以安全缓存的图像,因此我们也将其设置为max

在服务器块内,expires指令(头模块的一部分)设置缓存控制头。它使用地图中设置的$expires变量值。这样,生成的标题将根据文件类型而有所不同。

保存并关闭文件以退出。

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

代码语言:javascript
复制
sudo systemctl restart nginx

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

第4步 - 测试浏览器缓存

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

代码语言:javascript
复制
curl -I http://localhost/test.html

这次反应会有所不同。您应该看到另外两个HTTP响应标头:

代码语言:javascript
复制
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标题显示在过去的日期h和用no-cache设置的Cache-Control,它告诉浏览器总是问服务器是否有该文件的较新版本(用ETag头,像以前一样)。

您将看到测试图像文件的差异响应。

代码语言:javascript
复制
curl -I http://localhost/test.jpg
代码语言:javascript
复制
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的结果应该是相似的,因为JavaScript和样式表文件都是用缓存头设置的。

这意味着缓存控制标头已正确配置,您的网站将受益于性能提升和由于浏览器缓存导致的服务器请求减少。您应该根据您网站的内容自定义缓存设置,但本文中的默认值是一个合理的起点。

结论

headers模块可用于向响应添加任意头,但正确设置缓存控件头是其最有用的应用程序之一。它提高了网站用户的性能,特别是在移动运营商网络等具有更高延迟的网络上。它还可以在搜索引擎上产生更好的结果,将速度测试纳入其结果。设置浏览器缓存标头是Google的PageSpeed测试工具的主要建议之一。

想要了解更多关于使用Nginx的头模块实现浏览器缓存的相关教程,请前往腾讯云+社区学习更多知识。


参考文献:《How to Implement Browser Caching with Nginx's header Module on Ubuntu 16.04》

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
    • 准备
      • 第1步 - 创建测试文件
        • 第2步 - 检查默认行为
          • 第3步 - 配置缓存控制和过期标头
            • 第4步 - 测试浏览器缓存
              • 结论
              相关产品与服务
              云开发 CloudBase
              云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档