网站加载得越快,访问者留下的可能性就越大。当网站充满了由后台加载的脚本运行的图像和交互式内容时,打开网站并不是一项简单的任务。它包括从服务器逐个请求许多不同的文件。最大限度地减少这些请求的数量是加快网站速度的一种方法。
这可以通过多种方式完成,但其中一个更重要的步骤是配置浏览器缓存。这告诉浏览器,一次下载的文件可以从本地副本重用,而不是一次又一次地请求服务器。为此,必须引入告知浏览器行为方式的新HTTP响应标头。
这就是Nginx的标题模块发挥作用的地方。此模块可用于向响应添加任意任意标头,但其主要作用是正确设置缓存标头。在本教程中,我们将了解如何使用Nginx的头模块来实现浏览器缓存。
要学习本教程,您需要:
sudo
权限的非root账号的Ubuntu 16.04服务器,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。除了头模块,我们还将在本文中使用Nginx的地图模块。
在此步骤中,我们将在默认的Nginx目录中创建多个测试文件。稍后我们将使用这些文件来检查Nginx的默认行为,然后测试浏览器缓存是否正常工作。
为了决定通过网络提供什么类型的文件,Nginx不分析文件内容; 那会非常慢。相反,它只是查找文件扩展名以确定文件的MIME类型,这表示文件的用途。
由于这种行为,我们的测试文件的内容是无关紧要的。通过适当地命名文件,我们可以欺骗Nginx,例如,一个完全空的文件是一个图像而另一个是样式表。
在默认Nginx目录中使用truncate
创建名为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使用我们刚刚创建的文件在新安装上发送缓存控制头的行为方式。
默认情况下,所有文件都具有相同的默认缓存行为。为了探索这一点,我们将使用我们在步骤1中创建的HTML文件,但您可以使用任何示例文件运行这些测试。
因此,让我们检查是否test.html
提供了有关浏览器缓存响应的时间长度的任何信息。以下命令从我们的本地Nginx服务器请求文件并显示响应头。
curl -I http://localhost/test.html
您应该看到几个HTTP响应标头:
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
。
curl -I -H 'If-None-Match: "57d40685-400"' http://localhost/test.html
现在的反应会有所不同:
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模块附加缓存控制信息。这将使浏览器在本地缓存一些文件,而无需明确询问服务器是否可以这样做。
除了ETag
文件验证头之外,还有两个缓存控制响应头:Cache-Control
和Expires
。Cache-Control
是更新的版本,它有比Expires
更多的选项,如果你想更好地控制你的缓存行为通常更有用。
如果设置了这些标头,它们可以告诉浏览器所请求的文件可以在本地保存一段时间(包括永久)而无需再次请求它。如果未设置标头,浏览器将始终从服务器请求文件,期望200 OK或304 Not Modified响应。
我们可以使用头模块来设置这些HTTP头。头模块是核心Nginx模块,这意味着它不需要单独安装即可使用。
要添加标题模块,请用您喜欢的文本编辑器中打开在nano
中的默认的Nginx配置文件。
sudo nano /etc/nginx/sites-available/default
找到server
配置块,如下所示:
. . .
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
. . .
在此处添加以下两个新部分:一个在server
块之前,用于定义缓存不同文件类型的时间长度,以及一个在其中的一个,以适当地设置缓存头。
. . .
# 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/css
和application/javascript
,它们是样式表和Javascript文件,我们将值设置为max
。这意味着浏览器将尽可能长时间地缓存这些文件,从而减少了大量请求,因为通常有很多这些文件。~image/
,这是一个正则表达式会匹配所有的文件类型(包括image/
)在他们的MIME类型名称(如image/jpg
和image/png
)。与样式表一样,网站上通常有很多可以安全缓存的图像,因此我们也将其设置为max
。在服务器块内,expires
指令(头模块的一部分)设置缓存控制头。它使用地图中设置的$expires
变量值。这样,生成的标题将根据文件类型而有所不同。
保存并关闭文件以退出。
要启用新配置,请重新启动Nginx。
sudo systemctl restart nginx
接下来,让我们确保我们的新配置有效。
对测试HTML文件执行与以前相同的请求。
curl -I http://localhost/test.html
这次反应会有所不同。您应该看到另外两个HTTP响应标头:
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
头,像以前一样)。
您将看到测试图像文件的差异响应。
curl -I http://localhost/test.jpg
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.js
和test.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 删除。