天天看点

web系统js、css文件终极提速之gzip静态压缩+动态压缩

首先转载一个静态方法

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、火狐firefox、苹果的safari、谷歌的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}"/>

<macrodef name="gzipjscss">

<attribute name="dir" />

<sequential>

<for param="file">

<path>

<fileset dir="@{dir}" >

<include name="**/*.js"/>

<include name="**/*.css"/>

</path>

<gzip src="@{file}" destfile="@{file}gz"/>

</sequential>

</for>

</macrodef>

<macrodef name="replacejscssimport">

<!-- 修改对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" -->

<replacefilter token=".css"" value=".cssgz""/>

</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>

<url-pattern>*.cssgz</url-pattern>

</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 [email protected]

* @since 2009-01-08

*/

public class addheaderfilter implements filter {

map headers = new hashmap();

public void init(filterconfig config) throws servletexception {

//获取额外配置的header

string 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添加到当前response

for(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,这时就必须给系统安装如下几个补丁:

    其中q822002是必须的,而q831167和q832894我没试过不打会不会有影响,因为我在项目中碰到打开gzip的网页有问题时都把这三个补丁打上了,当时出现过问题的系统有windows 2000、windows xp sp0、windows xp sp1、windows xp sp2、一些被精简过的windows xp系统。

=====================

以下附上动态压缩方法

    简单到没什么可说的,使用nginx的配置文件nginx.conf打开压缩功能即可