web应用性能优化--采用gzip静态压缩+动态压缩方式压缩js、css文件

web应用性能优化–采用gzip静态压缩+动态压缩方式压缩js、css文件

Web应用中通常都会有大量的javascript和css文件,如开源的javascript框架jquery、extjs-core等等,这些js框架,动辄上百K,这些框架大多数时候能提升我们的开发效率,但是使用中稍不留神很容易导致系统响应缓慢。为了提高js、css文件的下载速度,在网络传输层面提高页面的响应速度,减小文件的大小才是终极之道。 这里所谓的减少JS、CSS文件大小并不是指我们常见的JS、CSS的代码压缩,这里主要采用的是gzip静态压缩的技术,是由于在项目中经过实践的检验,证实是可行、高效而且低风险的做法。
如果使用js压缩工具压缩js、css文件,当代码不规范时通常会存在不少的问题(通常是由于浏览器兼容性造成的,其中IE就是一个大BUG),而要解决这些问题,必须付出不少的人力资源。在写js代码的时候,由于是多人进行开发,即使有一定的编码规范,但是也避免不了代码中有不少不规范的地方,如在语句后忘了打“;”号,括号没有正确关闭,这样的代码在chorme里面运行没有问题,但是在IE里面可能应用就不行了;这样的代码经过js压缩后,导致的问题将更是让人哭笑不得。要解决这些js压缩后的问题,必须进行严格的测试,而往往都很难发现具体错在哪里,最终很有可能花费了大量的时间去排错。而使用gzip静态压缩技术后,这些由于代码不规范压缩而造成的问题,也就迎刃而解了,而且有可能压缩率比我们通常使用的js压缩(去掉注释,换行等)还要高许多。你唯一要担心的是浏览器是否支持gzip。而现在的浏览器却都已经完全支持gzip技术了(如微软的IE、火狐firefox、苹果的safari、谷歌的chrome等),所以就这个问题应经不是问题了。
以下为我在实际项目中使用的gzip静态压缩技术的所有细节,提供给大家参考。
* 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&quot;" value=".jsgz&quot;"/>
</replace>
<!-- 修改对css文件的引用为".cssgz" -->
<replace dir="@{dir}" encoding="utf-8">
<include name="**/*.jsp"/>
<include name="**/*.html"/>
<include name="**/*.htm"/>
<replacefilter token=".css&quot;" value=".cssgz&quot;"/>
</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 {
//获取额外配置的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);
}
}

以下附上动态压缩方法<参考自网络>
简单到没什么可说的,使用nginx的配置文件nginx.conf打开压缩功能即可
[csharp] view plaincopy
http {
include mime.types;
default_type application/octet-stream;
server_tokens off; ##禁止显示nginx软件的版本号
#log_format main ‘ remoteaddr remote_user [ timelocal]" 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_header    Host                $host:82;  
        proxy_set_header    X-Real-IP           $remote_addr;  
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;  
        proxy_set_header    Via                 "nginx";   
    }  
}   

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值