需要解決的問題
在做WEB系統開發時,為了提高性能會利用瀏覽器的緩存功能,其實即使不顯式的申明緩存,現代的瀏覽器都會對靜態文件(js、css、圖片之類)緩存。但也正因為這個問題導致一個問題,就是資源的緩存邏輯有時出現問題后服務器的最新版本文件無法更新客戶端的緩存。
這個問題會給用戶產生許多的困擾,當然首先是測試人員會很頭痛,一些看起來沒有修復的bug為什么開發要說做好了?這種時候我會無奈的說:ctrl+f5刷新一下。但這畢竟不是解決問題的方法。
思路與方法考慮
思路
之前沒有著手處理過這樣的問題,只是知道緩存可以通過時間戳、版本戳的方式來解決。說白了就是讓link的url不一樣瀏覽器自然會下載最新版本,想想這不是挺容易的事情嘛。項目緊也就沒當回事,等有時間了再來解決這個問題。
好了,最近有時間了開始解決。找了許多的方法,發現這確實是簡單的加一個版本號/時間戳就能解決:
<link rel="stylesheet" type="text/css" href="/css/common.css?ver=${sysVersion}" />
上面代碼中在資源后面加了一個?ver=${sysVersion}
注:項目中使用的是velocity,所以${sysVersion}是指velocity中的變量。
新的問題
但一個新問題產生,我們是使用hudsun+maven來進行構造并自動發布及部署到web服務器上。那么我們如何在maven構造時打上一個版本戳呢?
方法
- 通過某種方法生成一個版本號寫入到文件,系統啟動時加載此版本號,這樣velocity就能夠使用這個版本號從而解決緩存更新的問題。這種就是單一的統一版本號方法。
- 通過前端的編譯工具,grunt、F.I.S這類工具來完成,特別是F.I.S可以實現md5戳的模式,直接針對單個資源進行版本更新,這樣就比較精確也最大化了緩存的作用。
最后還是選擇了第一種方法,因為集成前端編譯工具的方法我沒有搞定T_T,原因:
1、F.I.S需要基于Node.js,這個又要配置許多東西,有點麻煩,當我自己搭建環境就反復了許多天,后來發現是網絡墻原因。
2、另外由于項目做的不是很規范,所以F.I.S生成時需要改動比較多的代碼,這個是我這種懶人不太愿意做的
于是先用簡單的方法解決之,最后經過1天的配置也確實完成了。
采用最簡單的單一版本號
單一的版本號一下子就簡化了解決問題的難度,只要想辦法在發布時生成一個版本號即可,那就不管是時間、數字或者其他什么,所有的資源都引用此版本號即可。找到了一個maven的插件:maven-svn-revision-number-plugin,這個插件可以獲取svn的版本號用作build號,這樣的好處就是只要有代碼提交就會有新版本產生。插件的代碼如下:
<plugin>
<groupId>com.google.code.maven-svn-revision-number-plugin</groupId>
<artifactId>maven-svn-revision-number-plugin</artifactId>
<version>1.7</version>
<configuration>
<verbose>true</verbose>
<entries>
<entry>
<prefix>prefix</prefix><!-- 版本戳的前綴-->
<depth>empty</depth>
</entry>
</entries>
</configuration>
<executions>
<execution>
<phase>validate</phase><!-- 生命周期階段-->
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.tmatesoft.svnkit</groupId><!-- 由于使用的是svn1.8版本,所以需要依賴這個插件-->
<artifactId>svnkit</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
</plugin>
這個插件的作用是在maven構造時獲取最新的svn版本號,然后利用maven的resources的filtering來在各個配置文件中作用變量使用。這樣就實現了構造時將版本號寫入文件。
resources的代碼:
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**.properties</include><!-- 只對properties文件進行處理-->
</includes>
<filtering>true</filtering><!-- 表示開啟變量嵌入 -->
</resource>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**.properties</exclude>
</excludes>
<filtering>false</filtering>
</resource>
</resources>
因為使用properties文件作為載體,所以上述的設置目的就是找到properties文件然后寫入版本號,我建了一個build_version.properties文件,里面寫了一個設置項:
build.version=${prefix.committedRevision}
${prefix.committedRevision}就可以獲取maven-svn-revision-number-plugin插件生成的版本號。
這樣設置好了后,使用Maven install就可以看到效果了,構造后在target目錄找到build_version.properties文件查看內容:
build.version=114912
此時就變成了一個數字。
在此看一看maven-svn-revision-number-plugin插件中會產生哪些變量:
[INFO] --- maven-svn-revision-number-plugin:1.7:revision (default) @ zrtc ---
[INFO] inspecting E:\workspace\web
[INFO] prefix = prefix
[INFO] depth = empty
[INFO] report unversioned = true
[INFO] report ignored = false
[INFO] report out-of-date = false
[INFO] collecting status information
[INFO] 114969 114912 E:\workspace\web
[INFO] setting properties
[INFO] prefix.repository =
[INFO] prefix.path =
[INFO] prefix.revision = 114969
[INFO] prefix.mixedRevisions = false
[INFO] prefix.committedRevision = 114912
[INFO] prefix.committedDate = 2015-10-23 09:03:39 +0800 (Fri, 23 Oct 2015)
[INFO] prefix.status =
[INFO] prefix.specialStatus =
可以看到插件有幾個變量,其中我使用了committedRevision,這個就是項目svn目錄最后一次提交的版本。revision 則是svn最新的版本號。在其他文件使用時需要加上prefix.這個前綴,這是在配置文件中定義過的,可以看上面的配置內容。
<prefix>prefix</prefix><!-- 版本戳的前綴-->
這個前綴自己取名就可以了。
自此功能完成,解決了資源版本更新的問題。看看瀏覽器前端頁面源代碼:
<link rel="stylesheet" href="/css/h_login.css?ver=114912" type="text/css">
未來的目標
最近因為解決前端客戶端資源更新的問題也看到了一些更好的方法,比如F.I.S這種前端工程構建工具。在了解的過程中知道了一個前端工程化的概念,有些大,但確實是未來的一種發展趨勢。在B/S開發越來越深入的階段,瀏覽器+服務器的這種開發平臺已經證明了其優越性,移動互聯網、云計算都已經體現了這種發展趨勢。而瀏覽器是最近10年人們用的最多的軟件了吧?而且瀏覽器已經證明了其無所不能,基于HTML+CSS就可以實現無數美秒的界面,原先常見的商業系統都也搬到了B/S架構下。可見HTML是多么牛逼的開發平臺。
站在這個時代如果還不能做點和時代相關的事情是不是感覺有點過時?所以在未來要思考一下前端系統的模塊化,最終實現工程化。
文章列表