最近疫情,着实无聊。简单总结点东西,打发时间。

这篇文章主要记录如何在tomcat或nginx中配置前端静态资源的缓存策略,力求简洁明了,不参杂其他无关配置项。

压缩

对于HTTP的压缩,是一种使用CPU时间来换取网络传输时间的技术。在现有网络环境下,CPU所消耗的时间远远小于网络传输所使用的时间。因此,如果服务器的CPU尚有盈余,则开启压缩是有益无害的。

静态资源

对于静态资源,有两种开启压缩的方式,一种是compress in time,另一种是precompression,下面有张图对比了这两种方式的异同。对于第二种,因为静态资源已经提前进行了压缩处理,当HTTP请求到达之后,可以直接响应已经压缩过的文件,所以可以节约服务器的CPU。因此,下面重点介绍如何针对第二种方式进行配置。




nginx 压缩 pdf nginx压缩js_服务器


CompressionWebpackPlugin

首先,我们需要构建出被压缩过的静态资源,这里可以借助CompressionWebpackPlugin来达成我们的目的。配置如下:


new CompressionPlugin({
  test: /.js$|.css$|.html$|.json$/, // 对哪些资源进行压缩
  threshold: 8192, // 超过多大的资源会被压缩,单位bytes
  minRatio: 0.8, // 压缩过后体积减少到80%以下的文件会被压缩
})


Nginx

如果你们使用的nginx作为静态资源服务器,可以简单在nginx.conf中的location区块中加上gzip_static on;就可以了。这个配置项主要是告诉nginx,如果客户端可以接收gzip过的文件,那么就寻找以.gz结尾的文件,如果存在,就返回它。是不是简单地超乎想象呢?

Tomcat

如果你们使用的tomcat作为服务器,情况稍微有点复杂,但也不困难。首先,如果你的tomcat版本>=8,那么你可以在web.xml中的DefaultServlet中加上这几行:


<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        ...
        <init-param>
            <param-name>gzip</param-name>
            <param-value>true</param-value>
        </init-param>
        ...
    </servlet>


这个配置的效果也是让tomcat去寻找.gz结尾的文件,如果客户端支持,就返回它。

如果你使用的tomcat>=9,而且想使用其他压缩算法的话,可以在同样的位置设置这个变量precompressed。它的值可以是br=.br,gzip=.gz,bzip2=.bz2。这个配置项告诉tomcat,若客户端能够接受被br压缩过的内容,那么返回以.br结尾的对应文件,以此类推。

API请求

对于API请求,因为其易变的特性,我们一般采用即时压缩的方式。那么,如果简单开启压缩呢,这里依旧分为nginx和tomcat两块来分开讲解。

Nginx

你可以将下面的配置简单定制后放在http区块里就可以了。


gzip  on;  # 开启gzip压缩
gzip_types application/json; # 对什么类型的资源进行压缩,因为API请求一般是json的,这里可以只配置json,具体需要根据情形来确定
gzip_min_length 8192; # 长度太短的话,压缩没有意义,单位是bytes


tomcat

tomcat的配置原理和nginx大致相同,只是属性名字有些区别,这个配置在server.xml中。


<Connector ...
               compression="on" # 开启压缩,也可以是个代表压缩等级的数字,0-9
               compressibleMimeType="application/json" # 对什么类型的资源进行压缩
               compressionMinSize="8192" # 长度大于多少进行压缩,单位是bytes
               />


缓存

缓存的配置一般多用于静态资源,对于API请求极少使用这一层级的缓存。这里只列举对于前端性能有帮助的配置。

缓存的原理

通俗来讲,静态资源的缓存通过HTTP头让客户端和服务器互通有无的过程。这事得从第一次说起,首先,客户端会向服务器要文件,服务器就返回了,顺便,服务器可以选择告诉客户端,这个文件的ETag(哈希)是什么,什么时候创建的,你可以缓存多长时间。客户端可以根据这些信息制定自己的策略。当这件事第二次发生的时候,客户端就可以告诉服务器,我这边有缓存,你看,这是文件的ETag,上次修改发生在什么时候,我是否希望使用本地的缓存。这时,服务器可以告诉客户端,你可以继续使用,或返回新的文件。

这个过程简单来说是这样,但实际情况要稍微复杂一些,这里不再赘述。具体一点的话,大家可以参考这里,https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching。

Nginx

Nginx的缓存策略分为两步。第一步,解决什么类型的资源缓存多长时间的问题。第二步,解决哪些位置的资源应用第一步中的策略问题。

第一步,将不同类型的MIME-TYPE映射到不同的缓存时间上,并存储在变量$expires中,示例:


map $sent_http_content_type $expires {
  default                                 off;
  # No content
  ""                                      off;
  ~*application/javascript                1y;
}


第二步,对跟路径应用该缓存,示例:


location / {
  root $h5;
  expires $expires;
}


Tomcat

在Tomcat中,情况也是类似的,只是叫法不一样。Tomcat中使用org.apache.catalina.filters.ExpiresFilter过滤器来控制缓存。同样也是两步走,第一步,通过过滤器解决什么类型的资源缓存多长时间的问题。第二步,解决哪些位置的资源应用该过滤器的问题。

第一步,配置过期过滤器ExpiresFilter。这里只配置了JavaScript,大家根据自己的实际情况进行配置。和nginx中的$expire一样,这里的过滤器名字可以随意取(但要表意),示例:


<filter>
  <filter-name>ExpiresFilter</filter-name>
  <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
  <init-param>
    <param-name>ExpiresByType application/javascript</param-name>
    <param-value>access plus 1 year</param-value>
  </init-param>
</filter>


第二步,应用该过滤器。注意,filter-name要和上面的匹配,要不然就起不了效果,示例:


<filter-mapping>
  <filter-name>ExpiresFilter</filter-name>
  <url-pattern>/*</url-pattern>
  <dispatcher>REQUEST</dispatcher>
</filter-mapping>


总结

这里只列举了比较常用的两种。可以看到,这两种的服务器配置方式非常相似,对于其他类型的服务器而言,也是大同小异的,具体可以参考这里,https://github.com/h5bp/server-configs。希望看完本篇文章的小伙伴能够有所收获,也希望大家的前端页面能够快的飞起。