什么是静态资源文件
顾名思义,静态资源文件就是js、css、img等非服务器动态运行生成的文件,统称为静态
资源文件。
为什么要缓存静态资源文件
静态资源文件是基本不会改变的,没必要每次都从服务器中获取。也就是说,我们每次向
服务器发送请求得到的静态资源是相同的。所以我们可以把静态资源缓存再浏览器,也就
是客户端,来进行性能优化。
虽然绝大多数css和js文件都只有几百k,但有些时候会存在如字体文件等超过1MB的文件,加载时间会达到一秒以上,就会极大的影响网页的整体加载速度,这时候就必须要对静态资源文件进行缓存。
实现缓存的几种方法
一、修改html文件
第一种方法就是在html文件的最上面加上这样一行代码:
<meta http-equiv="Cache-Control" content="max-age=7200" />
这句话的作用是修改服务器的响应该html文件的响应头,设置其中静态资源文件的缓存时间为7200秒。
说到这里首先要介绍一下服务器给浏览器的静态资源响应,按F12打开开发者调试工具,选择Network,如下图所示:
可以看到下面展示了许多js和css文件的加载信息,单击其中一条记录,可以看到他们的响应头信息。
可以看到,被红框圈上的部分,是和缓存有关的响应头信息。Cache-Control用于指定缓存机制,Expires用于声明缓存到期时间,Pragma则是为了兼容版本设置的,Http/1.1才可以识别Cache-Control,而Pragma对Http/1.0和Http1.1均生效。
因此我们之前做的操作就是修改这个响应头,让其由禁止缓存变为允许缓存。
然而我在做了这个操作之后并没用生效,响应头依旧没有改变。这是因为在页面进行设置的优先级是最低的,springboot内置的web服务器会将这个设置好的响应头进行覆盖。因此如果这个方法没有生效,我们就来使用第二种方法。
二、springboot配置
第二种方法原理相同,修改响应头。具体操作步骤见,这篇文章介绍的很详细,简单来说分为修改响应头和设置版本号两部分。设置版本号是为了每次修改后的js和css文件都会被更新,也就是浏览器通过版本号来区分自己缓存的js与css文件是否为最新的版本。
然而发现,在springboot进行配置后,响应头并未发生任何变化,没有实现缓存。这里可能有两个原因,第一是本身项目的架构问题,在更高的层级配置了静态资源响应头信息,在当前项目内修改会被覆盖;第二是在nginx进行了配置,nginx的优先级比springboot高,因此设置的响应头信息也会被覆盖。所以我们需要进行第三种配置,在nginx进行设置。
三、修改nginx配置文件
这里首先说明一下为何nginx的优先级更高,nginx是一个实现反向代理和负载均衡的轻量级web服务器,许多项目都会使用到它来做代理。可以理解为它是所有web服务器的统一入口和出口,也就是说我们所有的数据都是从springboot中集成的web服务器出来后,再由nginx代理,作处理后响应给浏览器。如下图所示,nginx最后对响应头作处理,所以会对之前的所有处理进行覆盖。
找到nginx的配置文件nginx.conf,百度搜索相应操作系统命令即可,添加配置文件内容:
location ~* \.(woff)$ {
proxy_pass http://kubernetes;
expires 1d;
}
这里的woff可以替换为css|js,即匹配所有css和js文件,这里我需要缓存的为字体文件,后缀为woff。之前查找了很多资料,没有第一行proxy_pass,配置后会出现匹配到的静态资源文件报404,是因为没有设置正确的代理路径,参考自己nginx配置文件中其它部分设置正确的路径即可。这样设置之后,重启nginx,发现可以进行缓存了,如下图所示:
绿色框框圈的部分已经发生了改变,同时响应码由原来的200变为了304
下面两张图是缓存前后的差别:
大小由之前的6.9MB变为350B,时间也由8秒变为100ms。
可以说我们的目的达到了,加载静态资源文件的时间极大的缩短了。但还不够完美,因为多发了一次304请求。也就是说浏览器会再发一次304请求,去问服务器究竟要不要从缓存中获取静态资源文件,确认后再从浏览器的缓存中获取。也就是说这个请求对我们来说是完全多余的,可以进一步优化。
我们发现红框中的响应头Pragma:no-cache依旧存在,这里的no-cache并不是不缓存的意思:
no-cache 可以在本地缓存,可以在代理服务器缓存,但是这个缓存要服务器验证才可以使用
no-store 彻底得禁用缓冲,本地和代理服务器都不缓冲,每次都从服务器获取
因此我们的304请求很可能是因为这个响应头造成的。我们要通过nginx去掉这个响应头。
nginx中清除响应头需要下载一个模块headers_more,这个模块可以实现响应头的清除功能。下载安装模块后需要对nginx重新编译才能生效。建议在运维的协助下完成。nginx中需要修改的配置如下:
location ~* \.(woff)$ {
proxy_pass http://kubernetes;
expires 1d;
more_clear_headers Pragma;
}
将Pragma这个响应头清除,之后重启nginx,结果如下图所示:
状态码已经变为200了,同时后面的(from memory cache)表明是从缓存中获取的该静态资源文件。
可以看到,Size已经变为(from memory cache),时间为0ms,静态资源文件缓存配置完成。
注意事项
最后的nginx配置我没有配置版本号,因为我缓存的是字体文件,也就是说是永远不会改变的。然而我们如果缓存的是js和css文件,每隔几周可能都会进行修改,这时候不设置版本号就是存在风险的,可能你浏览器端存有旧的css文件没有过期,这时候又没有版本号作区分,可能会导致无法获取最新的css文件。因此建议添加版本号,具体配置在springboot配置的链接中有详细说明,参考配置即可。