存在的問題:
合併、壓縮檔案主要有2方面的問題:
1. 每次發佈的時候需要執行一下自己寫的bat檔案或其他程式把檔案依照自己的設定合併、壓縮。
2. 因生產環境和開發環境需要載入的文件不一樣,生產環境為了需要載入合併、壓縮後的文件,而開發環境為了修改、調試方便,需要載入非合併、壓縮的文件,所以我們常常需要在JSP中類似與下面的判斷程式碼:
<c:if test="${env=='prod'}"> <script type="text/javascript" src="/js/all.js"></script> </c:if> <c:if test="${env=='dev'}"> <script type="text/javascript" src="/js/1.js"></script> <script type="text/javascript" src="/js/2.js"></script> <script type="text/javascript" src="/js/3.js"></script> </c:if>
快取問題:在現在JS滿天飛的時代,大家都知道快取能帶來的巨大好處,但快取確實非常麻煩的一個問題,相信很多人曾經歷過下面的情況:為了讓程式更快,在伺服器上為JS加上緩衝5天的程式碼,但產品更新後第二天就接到電話說系統出錯,詳細了解後就發現是快取引起的,讓用戶刪除緩存後就會OK。原因很簡單,就是你JS已經修改了,但用戶還在使用快取中的老JS。在經歷幾次這種情況,被領導數落了幾次後。沒辦法只能把JS的緩衝去掉,或改成8小時。但這樣就完全失去了快取的優勢了,哪我們到底需要解決哪些問題才能讓我們使用緩衝順心如意了?
1. 如何在修改了某個JS後,自動把所有引用該JS頁面的程式碼中加上1個版本號碼?
2. 該如何產生版本號,根據什麼來產生這個版本號。
可能有人為了解決上面的快取問題,寫了個JSP標籤,透過標籤讀取JS、css檔案的修改時間來作為版本號,從而來解決上面2個問題。但這個方法有以下幾個缺點:
1. 每次請求都要透過標籤讀取讀取檔案的修改時間,速度慢。當然你可以把檔案的修改時間放到快取中,這樣也會加到了記憶體使用量。
2. 在HTML靜態頁面中用不了
3. 如果你們公司是如下的部署發布方式(我們公司就是這樣),則會失效。每次發布,不是直接覆蓋之前的WEB目錄,運維的為的發布方便,要求每次發布直接給他們1個war包,他們會把之前WEB目錄整個刪除,然後上傳現在的war包,這樣就導致程式運作後,所有檔案的最後修改時間都是解壓縮war的時間。
分享自己專案中的處理方案:
為了解決上面討論過的問題,在下寫了1個如下的組件,組件中根據我們自己的實際情況使用了文件大小來做為文件的版本號,雖然在檔案修改很小(例如把字元a改成b),可能檔案大小並沒有變,導致版本號碼也不會變。
但這種機率還是很低的。當然如果你覺的使用文件修改時間作為版本號適合你,只需要修改一行程式碼就行,下面看下這個組件的處理流程(本來想用流程圖表達,最後還是覺的文字來的直白寫):
1. 程式啟動(contextInitialized)
2. 搜尋程式目錄下的所有merge.txt文件,根據merge.txt檔案的設定合併檔案, merge.txt檔案實例如下:
# 檔案合併設定檔,多個檔案以|隔開,以/開頭的表示從根目錄開始,
# 空格之後的檔名表示合併之後的檔名
# 把1,2,3合併到all檔中
1.js|2.js |3.js all.js
#合併CSS
/css/mian.css|/css/common.css all.css
3. 搜尋程式目錄下所有JS,CSS檔案(包括合併後的),每個文件都壓縮後產生對應的1個新檔案。
4. 搜尋程式目錄下所有JSP,html文件,把所有JS,css的引用代碼改成壓縮後並加了版本號的引用。
實例:
實例的文件結構如下圖:
看JSP原始代碼(程序運行前):
<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% boolean isDev = false; // 是否开发环境%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> <% if(isDev){ %> <script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery-1.4.2.js"></script> <script type="text/javascript" src="<%=request.getContextPath() %>/js/1.js"></script> <script type="text/javascript" src="<%=request.getContextPath() %>/js/2.js"></script> <link type="text/css" rel="stylesheet" href="<%=request.getContextPath() %>/css/1.css" /> <link type="text/css" rel="stylesheet" href="<%=request.getContextPath() %>/css/2.css" /> <% }else{ %> <script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery-1.4.2.js"></script> <script type="text/javascript" src="<%=request.getContextPath() %>/js/all.js"></script> <link type="text/css" rel="stylesheet" href="<%=request.getContextPath() %>/css/all.css" /> <% } %> </head> <body> <h1 class="c1">Hello World!</h1> </body> </html>
程序運行後JSP的代碼:
<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% boolean isDev = false; // 是否开发环境 %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> <% if(isDev){ %> <script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery-1.4.2-3gmin.js?99375"></script> <script type="text/javascript" src="<%=request.getContextPath() %>/js/1-3gmin.js?90"></script> <script type="text/javascript" src="<%=request.getContextPath() %>/js/2-3gmin.js?91"></script> <link type="text/css" rel="stylesheet" href="<%=request.getContextPath() %>/css/1-3gmin.css?35" /> <link type="text/css" rel="stylesheet" href="<%=request.getContextPath() %>/css/2-3gmin.css?18" /> <% }else{ %> <script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery-1.4.2-3gmin.js?99375"></script> <script type="text/javascript" src="<%=request.getContextPath() %>/js/all-3gmin.js?180"></script> <link type="text/css" rel="stylesheet" href="<%=request.getContextPath() %>/css/all-3gmin.css?53" /> <% } %> </head> <body> <h1 class="c1">Hello World!</h1> </body> </html>
加3gmin後綴的文件全部是程序啟動時自動產生的。
以上是高效能WEB開發 JS、CSS的合併、壓縮、快取管理的內容,更多相關文章請關注PHP中文網(www.php.cn)!