首先轉載一個靜態方法
web系統中免不了要使用大量的javascript和css檔案,如開源的javascript架構prototype、jquery、extjs-core等等,這些js架構,少都有幾百K,我曾經做過不少項目,都用了大量的js。特別是extjs,功能實在是強大,卻也是體積最大的一個js架構。使用中稍不留神很容易導致你的系統反映緩慢。為了提高js、css檔案的下載速度,從而提高頁面的響應速度,減小檔案的大小才是終極之道。減少這些檔案的大小已經有了不少的js壓縮公用程式可以做到,。在這裡重提gzip靜態壓縮的技術,是由於在項目中經過實踐的檢驗,證實是可行、高效而且低風險的做法。
如果使用js壓縮公用程式壓縮js、css檔案,會存在不少的問題,而要解決這些問題,必須付出不少的人力資源。因為通常一些舊的項目,或者一些只考慮在IE中使用的web系統,在寫js代碼的時候,有不少不規範的地方,如在語句後忘了打“;”號,ie可以通過,其它一些瀏覽器卻不認;js壓縮後,會導致甚至在ie裡面也無法運行。要解決這些js壓縮後的問題,必須進行嚴格的測試,而往往都很難發現具體錯在哪裡,最終很有可能花費了大量的時間去排錯。 而使用gzip靜態壓縮技術,卻絕對不會存在這些問題,而且壓縮率比js壓縮還要高許多。你唯一要擔心的是瀏覽器是否支援gzip。而現在的瀏覽器卻都已經完全支援gzip技術了(如微軟的IE、Firefoxfirefox、蘋果的safari、Google的chrome等),所以就不用擔心了。這裡有個小小的特殊,就是微軟的IE必須是要在IE6SP1或以上的版本才能很好的支援gzip,有些精間版的windows系統,就算是升級到IE6SP1或IE7都不能很好的支援gzip,這也沒關係,打上幾個關於gzip的微軟補丁就行了(後面有相關說明)。 以下為我在實際項目中使用的gzip靜態壓縮技術的所有細節,提供給大家參考。 對原有web系統的gzip靜態壓縮處理主要方法為: 1.將web系統中的*.js、*.css檔案預先通過gzip.exe壓縮儲存成*.jsgz 、*.cssgz 檔案;2.將web系統中引用js、css檔案的地方轉換為引用jsgz 、cssgz檔案 ;3.用戶端請求jsgz、cssgz檔案時,伺服器通過過濾器設定header,將所有以jsgz、cssgz結尾的檔案的請求增加設定“header Content-Encoding=gzip”的回應標頭。
下面為詳細的處理指令碼及相關設定檔的修改:
一)將web系統轉換為使用gzip靜態壓縮的web系統的ant指令碼<?xml version="1.0" encoding="UTF-8"?><project name="gzipcode" basedir="." default="rebuild"><!-- 引用ant的擴充包 --><taskdef resource="net/sf/antcontrib/antlib.xml" /><!-- web系統名(目錄名) --><property name="app.name" value="myapp"/><!-- web系統所在目錄(目前的目錄) --><property name="web.dir" value="."/><!-- 系統重構後所放到的路徑配置 --><property name="build.dir" value="${web.dir}/rebuild"/><target name="clean" description="清理"><delete dir="${build.dir}" /></target><target name="rebuild" depends="clean" description="重新構建項目"><copy todir="${build.dir}/${app.name}"><fileset dir="${web.dir}" ><include name="**/*.*"/></fileset></copy><gzipJSCSS dir="${build.dir}/${app.name}"/><replaceJSCSSImport dir="${build.dir}/${app.name}"/></target><macrodef name="gzipJSCSS"><attribute name="dir" /><sequential><for param="file"><path><fileset dir="@{dir}" ><include name="**/*.js"/><include name="**/*.css"/></fileset></path><sequential><gzip src="@{file}" destfile="@{file}gz"/></sequential></for></sequential></macrodef><macrodef name="replaceJSCSSImport"><attribute name="dir" /><sequential><!-- 修改對js檔案的引用為".jsgz" --><replace dir="@{dir}" encoding="utf-8"><include name="**/*.jsp"/><include name="**/*.html"/><include name="**/*.htm"/><replacefilter token=".js"" value=".jsgz""/></replace><!-- 修改對css檔案的引用為".cssgz" --><replace dir="@{dir}" encoding="utf-8"><include name="**/*.jsp"/><include name="**/*.html"/><include name="**/*.htm"/><replacefilter token=".css"" value=".cssgz""/></replace></sequential></macrodef></project>
二)修改web.xml設定檔<web-app ......><!-- 聲明gzip檔案過濾器 --><filter> <filter-name>gzipFileFilter</filter-name> <filter-class>com.dragon.web.AddHeaderFilter</filter-class> <init-param> <param-name>headers</param-name> <param-value>Content-Encoding=gzip</param-value> </init-param> </filter> ......<!-- gzip檔案過濾器配置 --><filter-mapping><filter-name>gzipFileFilter</filter-name><url-pattern>*.jsgz</url-pattern></filter-mapping><filter-mapping><filter-name>gzipFileFilter</filter-name><url-pattern>*.cssgz</url-pattern></filter-mapping>......</web-app ......>
三)過濾器原始碼package com.dragon.web;import java.io.IOException;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/*** 給請求檔案添加額外Header的過濾器* @author dragon rongjih@163.com* @since 2009-01-08*/public class AddHeaderFilter implements Filter {Map headers = new HashMap();public void init(FilterConfig config) throws ServletException {//擷取額外配置的headerString headersStr = config.getInitParameter("headers");String[] headers = headersStr.split(",");for(int i = 0; i < headers.length; i++) {String[] temp = headers[i].split("=");this.headers.put(temp[0].trim(), temp[1].trim());}}public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {if(req instanceof HttpServletRequest) {//僅對Http請求添加該過濾器的處理doFilter((HttpServletRequest)req, (HttpServletResponse)res, chain);}else {chain.doFilter(req, res);}}public void doFilter(HttpServletRequest request,HttpServletResponse response, FilterChain chain)throws IOException, ServletException {//將額外配置的header添加到當前Responsefor(Iterator it = headers.entrySet().iterator();it.hasNext();) {Map.Entry entry = (Map.Entry)it.next();response.addHeader((String)entry.getKey(),(String)entry.getValue());}chain.doFilter(request, response);}}
關於IE瀏覽器的gzip支援補充: IE必須是要在IE6SP1或以上的版本才能很好的支援gzip,有些精間版的windows系統,就算是升級到IE6SP1或IE7都不能很好的支援gzip,這時就必須給系統安裝如下幾個補丁:1.q822002 ---- 糾正IE6瀏覽包含Gzip編碼內容網頁時發生的錯誤2.q8311673.q832894 其中q822002是必須的,而Q831167和Q832894我沒試過不打會不會有影響,因為我在項目中碰到開啟gzip的網頁有問題時都把這三個補丁打上了,當時出現過問題的系統有windows 2000、windows XP SP0、windows XP SP1、windows XP SP2、一些被精簡過的windows XP系統。 =====================
以下附上動態壓縮方法 簡單到沒什麼可說的,使用nginx的設定檔nginx.conf開啟壓縮功能即可
http { include mime.types; default_type application/octet-stream;server_tokens off; ##禁止顯示nginx軟體的版本號碼 #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; gzip on; gzip_min_length 1000; gzip_buffers 4 8k; gzip_comp_level 9; #0-9 預設值為1,值越大壓縮率越高,消耗的cpu資源越多,傳輸量減小。 gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;### nginx做非80連接埠轉寄server { listen 82; server_name localhost; location / {proxy_pass http://127.0.0.1:7001;proxy_set_headerHost $host:82;proxy_set_headerX-Real-IP $remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_header Via "nginx"; }} }