<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 36, comments - 419, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    前言:    

         上一篇隨筆中網友 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代碼:
          1 import java.io.StringReader;

      2 import java.io.StringWriter;
      3 import java.util.*;
      4 import java.util.regex.*;
      5 
      6 /*******************************************
      7  * 壓縮jsp,html中的代碼,去掉所有空白符、換行符
      8  * @author  bearrui(ak-47)
      9  * @version 0.1
     10  * @date     2010-5-13
     11  *******************************************/
     12 public class HtmlCompressor {
     13     private static String tempPreBlock = "%%%HTMLCOMPRESS~PRE&&&";
     14     private static String tempTextAreaBlock = "%%%HTMLCOMPRESS~TEXTAREA&&&";
     15     private static String tempScriptBlock = "%%%HTMLCOMPRESS~SCRIPT&&&";
     16     private static String tempStyleBlock = "%%%HTMLCOMPRESS~STYLE&&&";
     17     private static String tempJspBlock = "%%%HTMLCOMPRESS~JSP&&&";
     18     
     19     private static Pattern commentPattern = Pattern.compile("<!--\\s*[^\\[].*?-->", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
     20     private static Pattern itsPattern = Pattern.compile(">\\s+?<", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
     21     private static Pattern prePattern = Pattern.compile("<pre[^>]*?>.*?</pre>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); 
     22     private static Pattern taPattern = Pattern.compile("<textarea[^>]*?>.*?</textarea>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
     23     private static Pattern jspPattern = Pattern.compile("<%([^-@][\\w\\W]*?)%>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
     24     // <script></script>
     25     private static Pattern scriptPattern = Pattern.compile("(?:<script\\s*>|<script type=['\"]text/javascript['\"]\\s*>)(.*?)</script>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
     26     private static Pattern stylePattern = Pattern.compile("<style[^>()]*?>(.+)</style>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
     27 
     28     // 單行注釋,
     29     private static Pattern signleCommentPattern = Pattern.compile("//.*");
     30     // 字符串匹配
     31     private static Pattern stringPattern = Pattern.compile("(\"[^\"\\n]*?\"|'[^'\\n]*?')");
     32     // trim去空格和換行符
     33     private static Pattern trimPattern = Pattern.compile("\\n\\s*",Pattern.MULTILINE);
     34     private static Pattern trimPattern2 = Pattern.compile("\\s*\\r",Pattern.MULTILINE);
     35     // 多行注釋
     36     private static Pattern multiCommentPattern = Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
     37 
     38     private static String tempSingleCommentBlock = "%%%HTMLCOMPRESS~SINGLECOMMENT&&&";  // //占位符
     39     private static String tempMulitCommentBlock1 = "%%%HTMLCOMPRESS~MULITCOMMENT1&&&";  // /*占位符
     40     private static String tempMulitCommentBlock2 = "%%%HTMLCOMPRESS~MULITCOMMENT2&&&";  // */占位符
     41     
     42     
     43     public static String compress(String html) throws Exception {
     44         if(html == null || html.length() == 0) {
     45             return html;
     46         }
     47         
     48         List<String> preBlocks = new ArrayList<String>();
     49         List<String> taBlocks = new ArrayList<String>();
     50         List<String> scriptBlocks = new ArrayList<String>();
     51         List<String> styleBlocks = new ArrayList<String>();
     52         List<String> jspBlocks = new ArrayList<String>();
     53         
     54         String result = html;
     55         
     56         //preserve inline java code
     57         Matcher jspMatcher = jspPattern.matcher(result);
     58         while(jspMatcher.find()) {
     59             jspBlocks.add(jspMatcher.group(0));
     60         }
     61         result = jspMatcher.replaceAll(tempJspBlock);
     62         
     63         //preserve PRE tags
     64         Matcher preMatcher = prePattern.matcher(result);
     65         while(preMatcher.find()) {
     66             preBlocks.add(preMatcher.group(0));
     67         }
     68         result = preMatcher.replaceAll(tempPreBlock);
     69         
     70         //preserve TEXTAREA tags
     71         Matcher taMatcher = taPattern.matcher(result);
     72         while(taMatcher.find()) {
     73             taBlocks.add(taMatcher.group(0));
     74         }
     75         result = taMatcher.replaceAll(tempTextAreaBlock);
     76         
     77         //preserve SCRIPT tags
     78         Matcher scriptMatcher = scriptPattern.matcher(result);
     79         while(scriptMatcher.find()) {
     80             scriptBlocks.add(scriptMatcher.group(0));
     81         }
     82         result = scriptMatcher.replaceAll(tempScriptBlock);
     83         
     84         // don't process inline css 
     85         Matcher styleMatcher = stylePattern.matcher(result);
     86         while(styleMatcher.find()) {
     87             styleBlocks.add(styleMatcher.group(0));
     88         }
     89         result = styleMatcher.replaceAll(tempStyleBlock);
     90         
     91         //process pure html
     92         result = processHtml(result);
     93         
     94         //process preserved blocks
     95         result = processPreBlocks(result, preBlocks);
     96         result = processTextareaBlocks(result, taBlocks);
     97         result = processScriptBlocks(result, scriptBlocks);
     98         result = processStyleBlocks(result, styleBlocks);
     99         result = processJspBlocks(result, jspBlocks);
    100         
    101         preBlocks = taBlocks = scriptBlocks = styleBlocks = jspBlocks = null;
    102         
    103         return result.trim();
    104     }
    105     
    106     private static String processHtml(String html) {
    107         String result = html;
    108         
    109         //remove comments
    110 //        if(removeComments) {
    111             result = commentPattern.matcher(result).replaceAll("");
    112 //        }
    113         
    114         //remove inter-tag spaces
    115 //        if(removeIntertagSpaces) {
    116             result = itsPattern.matcher(result).replaceAll("><");
    117 //        }
    118         
    119         //remove multi whitespace characters
    120 //        if(removeMultiSpaces) {
    121             result = result.replaceAll("\\s{2,}"," ");
    122 //        }
    123                 
    124         return result;
    125     }
    126     
    127     private static String processJspBlocks(String html, List<String> blocks){
    128         String result = html;
    129         for(int i = 0; i < blocks.size(); i++) {
    130             blocks.set(i, compressJsp(blocks.get(i)));
    131         }
    132         //put preserved blocks back
    133         while(result.contains(tempJspBlock)) {
    134             result = result.replaceFirst(tempJspBlock, Matcher.quoteReplacement(blocks.remove(0)));
    135         }
    136         
    137         return result;
    138     }
    139     private static String processPreBlocks(String html, List<String> blocks) throws Exception {
    140         String result = html;
    141         
    142         //put preserved blocks back
    143         while(result.contains(tempPreBlock)) {
    144             result = result.replaceFirst(tempPreBlock, Matcher.quoteReplacement(blocks.remove(0)));
    145         }
    146         
    147         return result;
    148     }
    149     
    150     private static String processTextareaBlocks(String html, List<String> blocks) throws Exception {
    151         String result = html;
    152         
    153         //put preserved blocks back
    154         while(result.contains(tempTextAreaBlock)) {
    155             result = result.replaceFirst(tempTextAreaBlock, Matcher.quoteReplacement(blocks.remove(0)));
    156         }
    157         
    158         return result;
    159     }
    160     
    161     private static String processScriptBlocks(String html, List<String> blocks) throws Exception {
    162         String result = html;
    163         
    164 //        if(compressJavaScript) {
    165             for(int i = 0; i < blocks.size(); i++) {
    166                 blocks.set(i, compressJavaScript(blocks.get(i)));
    167             }
    168 //        }
    169         
    170         //put preserved blocks back
    171         while(result.contains(tempScriptBlock)) {
    172             result = result.replaceFirst(tempScriptBlock, Matcher.quoteReplacement(blocks.remove(0)));
    173         }
    174         
    175         return result;
    176     }
    177     
    178     private static String processStyleBlocks(String html, List<String> blocks) throws Exception {
    179         String result = html;
    180         
    181 //        if(compressCss) {
    182             for(int i = 0; i < blocks.size(); i++) {
    183                 blocks.set(i, compressCssStyles(blocks.get(i)));
    184             }
    185 //        }
    186         
    187         //put preserved blocks back
    188         while(result.contains(tempStyleBlock)) {
    189             result = result.replaceFirst(tempStyleBlock, Matcher.quoteReplacement(blocks.remove(0)));
    190         }
    191         
    192         return result;
    193     }
    194     
    195     private static String compressJsp(String source)  {
    196         //check if block is not empty
    197         Matcher jspMatcher = jspPattern.matcher(source);
    198         if(jspMatcher.find()) {
    199             String result = compressJspJs(jspMatcher.group(1));
    200             return (new StringBuilder(source.substring(0, jspMatcher.start(1))).append(result).append(source.substring(jspMatcher.end(1)))).toString();
    201         } else {
    202             return source;
    203         }
    204     }    
    205     private static String compressJavaScript(String source)  {
    206         //check if block is not empty
    207         Matcher scriptMatcher = scriptPattern.matcher(source);
    208         if(scriptMatcher.find()) {
    209             String result = compressJspJs(scriptMatcher.group(1));
    210             return (new StringBuilder(source.substring(0, scriptMatcher.start(1))).append(result).append(source.substring(scriptMatcher.end(1)))).toString();
    211         } else {
    212             return source;
    213         }
    214     }
    215         
    216     private static String compressCssStyles(String source)  {
    217         //check if block is not empty
    218         Matcher styleMatcher = stylePattern.matcher(source);
    219         if(styleMatcher.find()) {
    220             // 去掉注釋,換行
    221             String result= multiCommentPattern.matcher(styleMatcher.group(1)).replaceAll("");
    222             result = trimPattern.matcher(result).replaceAll("");
    223             result = trimPattern2.matcher(result).replaceAll("");
    224             return (new StringBuilder(source.substring(0, styleMatcher.start(1))).append(result).append(source.substring(styleMatcher.end(1)))).toString();
    225         } else {
    226             return source;
    227         }
    228     }
    229     
    230     private static String compressJspJs(String source){
    231         String result = source;
    232         // 因注釋符合有可能出現在字符串中,所以要先把字符串中的特殊符好去掉
    233         Matcher stringMatcher = stringPattern.matcher(result);
    234         while(stringMatcher.find()){
    235             String tmpStr = stringMatcher.group(0);
    236             
    237             if(tmpStr.indexOf("//"!= -1 || tmpStr.indexOf("/*"!= -1 || tmpStr.indexOf("*/"!= -1){
    238                 String blockStr = tmpStr.replaceAll("//", tempSingleCommentBlock).replaceAll("/\\*", tempMulitCommentBlock1)
    239                                 .replaceAll("\\*/", tempMulitCommentBlock2);
    240                 result = result.replace(tmpStr, blockStr);
    241             }
    242         }
    243         // 去掉注釋
    244         result = signleCommentPattern.matcher(result).replaceAll("");
    245         result = multiCommentPattern.matcher(result).replaceAll("");
    246         result = trimPattern2.matcher(result).replaceAll("");
    247         result = trimPattern.matcher(result).replaceAll(" ");
    248         // 恢復替換掉的字符串
    249         result = result.replaceAll(tempSingleCommentBlock, "//").replaceAll(tempMulitCommentBlock1, "/*")
    250                 .replaceAll(tempMulitCommentBlock2, "*/");
    251         
    252         return result;
    253     }
    254 }
    255 

    使用注意事項

     

          使用了上面方法后,再運行程序,是不是發現每個頁面查看源代碼的時候都變成1行啦,還不錯吧,但是在使用的時候還是要注意一些問題:

               1. 嵌入js本來想調用yuicompressor來壓縮,yuicompressor壓縮JS前,會先編譯js是否合法,因我們嵌入的js中可能很多會用到一些服務器端代碼,比如 var now = <%=DateTime.now %> ,這樣的代碼會編譯不通過,所以無法使用yuicompressor。

                  最后只能自己寫壓縮JS代碼,自己寫的比較粗燥,所以有個問題還解決,就是如果開發人員在一句js代碼后面沒有加分號的話,壓縮成1行就很有可能出問題。所以使用這個需要保證每條語句結束后都必須帶分號。

     

               2. 因為是在程序啟動的時候壓縮所有jsp(aspx),所以如果是用戶請求的時候動態產生的html就無法壓縮。



        有需要請查看:高性能WEB開發系列


    [作者]:BearRui(AK-47)
    [博客]: http://www.tkk7.com/bearrui/
    [聲明]:本博所有文章版權歸作者所有(除特殊說明以外),轉載請注明出處.
    英雄,別走啊,幫哥評論下:  

    精彩推薦 好文要頂 水平一般 看不懂 還需努力

    評論

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-05-17 09:40 by BeanSoft
    頂下先!

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-05-17 09:53 by 麗可酷
    真不錯,謝謝

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-05-17 10:02 by BearRui(AK-47)
    呵呵,謝謝2位的支持。

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-05-17 13:58 by 16樓
    挺好就是注意事項挺多的!

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-05-17 14:14 by BearRui(AK-47)
    @16樓
    是啊,還有待完善啊,^_^

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-05-18 11:29 by 牙牙學語
    謝謝分享,學習!
    其實也可以用ant腳本在打包時對頁面文件做些處理

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-05-18 12:05 by BearRui(AK-47)
    @牙牙學語
    是可以,我最開始想寫maven插件,在部署的時候自動處理,但是寫的比較麻煩,感覺還是這樣寫比較簡單。

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-06-09 17:05 by panasia
    今天來到這里學到不少東西。。也下了不少好東西。呵呵。。感謝博主。。這個東西對我現在這個項目來說有點杯具。。因為我發現我們的程序員在寫代碼的時候。。有的地方沒有加分號。。。囧。。

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-06-09 17:08 by BearRui(AK-47)
    @panasia
    呵呵,也非常感謝你的支持,看到你的很多回復。

    我這個html壓縮做的確是有點簡單,因為JS分析比較復雜,所以目前暫時只能要求開發人員注意編寫JS的格式了。

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-06-10 18:47 by panasia
    http://www.cnblogs.com/sohighthesky/archive/2010/05/14/uedsky-html-compressor.html
    博主,我今天看到這篇文章。這個blog不知道是不是你的?我看了下。。好像是盜用了你的文章。。還被轉到http://www.ued163.com/?p=814上面了

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-06-10 23:13 by BearRui(AK-47)
    @panasia
    呵呵,看日期好像他還在我之前發布的。應該只是巧合而已。

    另:我在cnblogs的博客地址是:
    http://www.cnblogs.com/BearsTaR/

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-06-24 13:37 by tiffany discount
    盡管看不懂,但可以看得出博主很有才。

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-06-24 13:55 by BearRui(AK-47)
    @tiffany discount
    呵呵,謝謝。

    # re: WEB高性能開發(10) - 瘋狂的HTML壓縮  回復  更多評論   

    2010-11-27 17:16 by Dylan
    寫的不錯
    主站蜘蛛池模板: 天天摸天天操免费播放小视频| 拔擦拔擦8x华人免费久久| 亚洲成a人片在线观看中文app| 在线观看视频免费国语| 日本一区二区三区在线视频观看免费 | 亚洲精品在线免费观看视频| 成年女人毛片免费视频| 无人视频在线观看免费播放影院| 久久精品国产亚洲AV麻豆不卡| 成人毛片免费观看| 久久美女网站免费| 亚洲欧美日韩自偷自拍| 亚洲精品无码不卡在线播HE| 免费无码AV片在线观看软件| 国产久爱免费精品视频 | 亚洲国产一成久久精品国产成人综合| 日本亚洲欧洲免费天堂午夜看片女人员| 欧洲 亚洲 国产图片综合| 久久亚洲色一区二区三区| 成人爽A毛片免费看| 久久青青草原国产精品免费| 国产成人精品久久亚洲高清不卡| 亚洲va久久久噜噜噜久久| 国产免费av一区二区三区| 亚洲一级免费视频| 人人公开免费超级碰碰碰视频| 亚洲日韩中文字幕| 亚洲开心婷婷中文字幕| 日本免费网站观看| 国产一卡二卡四卡免费| a级毛片在线免费看| 在线亚洲v日韩v| 亚洲日产乱码一二三区别 | 亚洲电影在线免费观看| 亚洲色爱图小说专区| 国产最新凸凹视频免费| 91免费播放人人爽人人快乐| 日本免费中文字幕| jizz中国免费| 免费人成视频在线播放| 亚洲国产AV一区二区三区四区|