WEB高性能开发之疯狂的高性能开发之疯狂的HTML压缩压缩
一篇随笔中网友 skyaspnet 问我如何压缩HTML,当时回答是推荐他使用gzip,后来想想,要是能把所有的
html,jsp(aspx)在运行前都压缩成1行未免不是一件好事啊。
一般我们启动gzip都比较少对html启动gzip,因为现在的html都是动态的,不会使用浏览器缓存,而启用gzip的话每次请求都
需要压缩,会比较消耗服务器资源,对js,css启动gzip比较好是因为js,css都会使用缓存。我个人觉得的压缩html的最大好处就
是一本万利,只要写好了一次,以后所有程序都可以使用,不会增加任何额外的开发工作。
在“JS、CSS的合并、压缩、缓存管理”一文中说到自己写过的1个自动合并、压缩JS,CSS,并添加版本号的组件。这次把压缩
html的功能也加入到该组件中,流程很简单,就是在程序启动(contextInitialized or Application_Start)的时候扫描所有
html,jsp(aspx)进行压缩。
压缩的注意事项:
实现的方式主要是用正则表达式去查找,替换。在html压缩的时候,主要要注意下面几点:
1. pre,textarea 标签里面的内容格式需要保留,不能压缩。
2. 去掉html注释的时候,有些注释是不能去掉的,比如:<!--[if IE 6]> ..... <![endif]-->
3. 压缩嵌入式js中的注释要注意,因为可能注释符号会出现在字符串中,比如: var url = "http://www.cnblogs.com"; // 前面
的//不是注释
去掉JS换行符的时候,不能直接跟一下行动内容,需要有空格,考虑下面的代码:
else
return;
如果不带空格,则变成elsereturn。
4. jsp(aspx) 中很有可能会使用<% %>嵌入一些服务器代码,这个时候也需要单独处理,里面注释的处理方法跟js的一样。
源代码:
下面是java实现的源代码,也可以 猛击此处 下载该代码,相信大家都看的懂,也很容易改成net代码:
复制代码 代码如下:
import java.io.StringReader;
import java.io.StringWriter;
import java.util.*;
import java.util.regex.*;
/*******************************************
* 压缩jsp,html中的代码,去掉所有空白符、换行符
* @author bearrui(ak-47)
* @version 0.1
* @date 2010-5-13
*******************************************/
public class HtmlCompressor {
private static String tempPreBlock = "%%%HTMLCOMPRESS~PRE&&&";
private static String tempTextAreaBlock = "%%%HTMLCOMPRESS~TEXTAREA&&&";
private static String tempScriptBlock = "%%%HTMLCOMPRESS~SCRIPT&&&";
private static String tempStyleBlock = "%%%HTMLCOMPRESS~STYLE&&&";
private static String tempJspBlock = "%%%HTMLCOMPRESS~JSP&&&";
private static Pattern commentPattern = Pattern.compile("<!--\s*[^\[].*?-->", Pattern.DOTALL | Pattern.CASE_INSENSITIVE
| Pattern.MULTILINE);
private static Pattern itsPattern = Pattern.compile(">\s+?<", Pattern.DOTALL | Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE);
private static Pattern prePattern = Pattern.compile("<pre[^>]*?>.*?</pre>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE);
private static Pattern taPattern = Pattern.compile("<textarea[^>]*?>.*?</textarea>", Pattern.DOTALL |
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
private static Pattern jspPattern = Pattern.compile("<%([^-@][\w\W]*?)%>", Pattern.DOTALL |
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
// <script></script>
private static Pattern scriptPattern = Pattern.compile("(?:<script\s*>|<script type=['\"]text/javascript['\"]\s*>)(.*?)</script>",
Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
private static Pattern stylePattern = Pattern.compile("<style[^>()]*?>(.+)</style>", Pattern.DOTALL |
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
// 单行注释,
private static Pattern signleCommentPattern = Pattern.compile("//.*");
// 字符串匹配
private static Pattern stringPattern = Pattern.compile("(\"[^\"\n]*?\"|'[^'\n]*?')");
// trim去空格和换行符
private static Pattern trimPattern = Pattern.compile("\n\s*",Pattern.MULTILINE);
private static Pattern trimPattern2 = Pattern.compile("\s*\r",Pattern.MULTILINE);
// 多行注释
private static Pattern multiCommentPattern = Pattern.compile("/\*.*?\*/", Pattern.DOTALL | Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE);