基于maven对JS,CSS统一加版本号
在写WEB应用的时候,每次对JS/CSS文件做的修改,对于用户来说,都很郁闷;一不注意,接到用户的投诉说:为啥我的不能用了。呃,浏览器缓存,麻烦您老清一下缓存。好吧,用户说了,我为啥要清;(每次升级,能挨个通知用户不?或者首页挂个广而告之:咱系统升级了,遇到不能用的时候,劳烦您老 Ctrl+F5 吧;真要这样,估摸着耳朵会红好多天的啊。。。)
其实浏览器缓存引发的JS、CSS的问题,是有办法搞定的;最狠的做法,就是禁止浏览器缓存,别缓存了,都来我服务器上拿吧;但这样的话,会造成服务器的负载过高,另外用户端由于每次访问页面都需要下载一波的JS、CSS文件,影响了体验,尤其是一些大的JS/CSS文件的时候;
当然,还有一种方法就是每次js/css文件有变动,就在引用的地方加上版本的控制,改个版本号;比如:<script src="http://xxx.com/js/a.js?v=110" type="text/javascript">
这样的话,第一次因为请求的url不一样了,所以,每次还是会到服务器上拉取的。之后由于版本号不变了,那么浏览器的本地缓存又可以用了,减轻了服务器压力,也提升了加载速度。这个蛮好的; 但是,话说回来了,加版本号这事儿,让每个开发来做,有点不靠谱,而且,有遗漏也不好说呀;搞个自动的呗;
加版本号的方法
- 写个方法能够自动生成
<script>
标签
这种方法大致的做法的是: 首先:写一个页面上用的方法,比如:JSP,就写个自定义标签;velocity,就写个宏方法; 其次:在原来的
<script src="http://xxx.com/js/a.js?v=110" type="text/javascript">
使用自定义标签进行编写,例如:$func("http://xxx.com/js/a.js") ;通过这个标签,或者是宏,来生成以上的 script 标签; 如果是整个应用刚开始做的时候,推荐这么处理;而且,还可以将业务的JS,和第三方公共JS区分开;比如第三方JS(jquery.js)之类的,基本上引入之后就不会修改,而且往往这种的第三方JS文件都比较大;而业务的JS,那是变化大了,只需要针对这部分JS做特殊处理即可;
- 通过工具统一加版本
工具统一加版本,也就是说,不管啥情况,只要是页面上引入的 js / css 在打包阶段都统一在后面补上版本号的处理; 这个会减轻第一种方式的工作量,而且对于开发来说,不用特别注意说,呃,引入JS了,我要改改的思路; 如果原来项目工程能够规划的好,比如将第三方JS/CSS 和 业务的JS/CSS 通过目录区分开,也可以只针对引入的业务 js/css 设置版本号; 由于我是一个javaer ,项目工程用了maven,那我自然想着maven在打包的时候,是否可以进行批量替换;一查插件,还真有了;
maven-replacer-plugin
这是将文件中匹配的内容替换为给定值的maven插件,就是通过这个插件,来对上面提到的js/css文件自动加版本号。想想也是,其实原来是写着<script src="http://xxx.com/js/a.js" type="text/javascript">
的;那只需要在.js
后面加上?v=110
就好了呀,用替换就可以了; maven-replacer-plugin 插件的官方说明:https://code.google.com/archive/p/maven-replacer-plugin/ ;
使用方式
在 pom.xml 的build--> plugin 中引入以下的设置;
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>${project.build.directory}/${project.build.finalName}/WEB-INF/view/**/*.jsp</include>
</includes>
<replacements>
<replacement>
<token>\.css\"</token>
<value>.css?v=${maven.build.timestamp}\"</value>
</replacement>
<replacement>
<token>\.js\"</token>
<value>.js?v=${maven.build.timestamp}\"</value>
</replacement>
</replacements>
</configuration>
</plugin>
以上配置的意思是说,针对文件:${project.build.directory}/${project.build.finalName}/WEB-INF/view/**/*.jsp
在prepare-package 阶段 进行 replacements 部分内容的替换; tocken是要替换的内容; value是替换后的内容; maven.build.timestamp 是指maven 打包的时间戳; 实际上,为了配合使用,需要在war打包的prepare-packege 阶段将war包的内容解压出来;所以在pom.xml中,还需要加上以下的配置
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<useCache>true</useCache>
</configuration>
<executions>
<execution>
<id>prepare-war</id>
<phase>prepare-package</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
</plugin>
配置都搞定之后,按正常的打包方式走一个:mvn clean package -U -e -Dmaven.test.skip
;在target目录下生成 war文件,我们解压,找几个文件看看效果;
红色部分,就是以上配置出来的效果,会自动带上打包的时间戳,但问题来了,为啥那个时间戳那么的怪异,又是T,又是Z的;我有强迫症,我要存数字。好吧,这是因为默认的 maven.build.timestamp 的时间格式的问题,设置一个呗: <maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
再次打包,看看效果
好了吧,这回可以了哈;
附上简要的pom.xml内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>demo-web</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>demo-web Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--略了-->
</dependencies>
<build>
<finalName>demo-web</finalName>
<plugins>
<!-- compiler插件, 设定JDK版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<useCache>true</useCache>
</configuration>
<executions>
<execution>
<id>prepare-war</id>
<phase>prepare-package</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>${project.build.directory}/${project.build.finalName}/WEB-INF/view/**/*.jsp</include>
</includes>
<replacements>
<replacement>
<token>\.css\"</token>
<value>.css?v=${maven.build.timestamp}\"</value>
</replacement>
<replacement>
<token>\.css\'</token>
<value>.css?v=${maven.build.timestamp}\'</value>
</replacement>
<replacement>
<token>\.js\"</token>
<value>.js?v=${maven.build.timestamp}\"</value>
</replacement>
<replacement>
<token>\.js\'</token>
<value>.js?v=${maven.build.timestamp}\'</value>
</replacement>
</replacements>
</configuration>
</plugin>
</plugins>
</build>
</project>