天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

WEB高性能開(kāi)發(fā)之瘋狂的HTML壓縮

一般我們啟動(dòng)gzip都比較少對(duì)html啟動(dòng)gzip,因?yàn)楝F(xiàn)在的html都是動(dòng)態(tài)的,不會(huì)使用瀏覽器緩存,而啟用gzip的話每次請(qǐng)求都需要壓縮,會(huì)比較消耗服務(wù)器資源,對(duì)js,css啟動(dòng)gzip比較好是因?yàn)閖s,css都會(huì)使用緩存。我個(gè)人覺(jué)得的壓縮html的最大好處就是一本萬(wàn)利,只要寫(xiě)好了一次,以后所有程序都可以使用,不會(huì)增加任何額外的開(kāi)發(fā)工作。
在“JS、CSS的合并、壓縮、緩存管理”一文中說(shuō)到自己寫(xiě)過(guò)的1個(gè)自動(dòng)合并、壓縮JS,CSS,并添加版本號(hào)的組件。這次把壓縮html的功能也加入到該組件中,流程很簡(jiǎn)單,就是在程序啟動(dòng)(contextInitialized or Application_Start)的時(shí)候掃描所有html,jsp(ASPx)進(jìn)行壓縮。
壓縮的注意事項(xiàng):
實(shí)現(xiàn)的方式主要是用正則表達(dá)式去查找,替換。在html壓縮的時(shí)候,主要要注意下面幾點(diǎn):
1. pre,textarea 標(biāo)簽里面的內(nèi)容格式需要保留,不能壓縮。
2. 去掉html注釋的時(shí)候,有些注釋是不能去掉的,比如:<!--[if IE 6]> ..... <![endif]-->
3. 壓縮嵌入式j(luò)s中的注釋要注意,因?yàn)榭赡茏⑨尫?hào)會(huì)出現(xiàn)在字符串中,比如: var url = "http://www.cnblogs.com"; // 前面的//不是注釋
去掉JS換行符的時(shí)候,不能直接跟一下行動(dòng)內(nèi)容,需要有空格,考慮下面的代碼:
else
return;
如果不帶空格,則變成elsereturn。
4. jsp(ASPx) 中很有可能會(huì)使用<% %>嵌入一些服務(wù)器代碼,這個(gè)時(shí)候也需要單獨(dú)處理,里面注釋的處理方法跟js的一樣。
源代碼:
下面是Java實(shí)現(xiàn)的源代碼,也可以 猛擊此處 下載該代碼,相信大家都看的懂,也很容易改成NET代碼:
復(fù)制代碼 代碼如下:
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("http://.*");
// 字符串匹配
private static Pattern stringPattern = Pattern.compile("(/"[^/"http://n]*?/"|'[^'//n]*?')");
// trim去空格和換行符
private static Pattern trimPattern = Pattern.compile("http://n//s*",Pattern.MULTILINE);
private static Pattern trimPattern2 = Pattern.compile("http://s*//r",Pattern.MULTILINE);
// 多行注釋
private static Pattern multiCommentPattern = Pattern.compile("http:///*.*?//*/", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
private static String tempSingleCommentBlock = "%%%HTMLCOMPRESS~SINGLECOMMENT&&&"; // //占位符
private static String tempMulitCommentBlock1 = "%%%HTMLCOMPRESS~MULITCOMMENT1&&&"; // /*占位符
private static String tempMulitCommentBlock2 = "%%%HTMLCOMPRESS~MULITCOMMENT2&&&"; // */占位符

public static String compress(String html) throws Exception {
if(html == null || html.length() == 0) {
return html;
}
List<String> preBlocks = new ArrayList<String>();
List<String> taBlocks = new ArrayList<String>();
List<String> scriptBlocks = new ArrayList<String>();
List<String> styleBlocks = new ArrayList<String>();
List<String> jspBlocks = new ArrayList<String>();
String result = html;
//preserve inline Java code
Matcher jspMatcher = jspPattern.matcher(result);
while(jspMatcher.find()) {
jspBlocks.add(jspMatcher.group(0));
}
result = jspMatcher.replaceAll(tempJspBlock);
//preserve PRE tags
Matcher preMatcher = prePattern.matcher(result);
while(preMatcher.find()) {
preBlocks.add(preMatcher.group(0));
}
result = preMatcher.replaceAll(tempPreBlock);
//preserve TEXTAREA tags
Matcher taMatcher = taPattern.matcher(result);
while(taMatcher.find()) {
taBlocks.add(taMatcher.group(0));
}
result = taMatcher.replaceAll(tempTextAreaBlock);
//preserve SCRIPT tags
Matcher scriptMatcher = scriptPattern.matcher(result);
while(scriptMatcher.find()) {
scriptBlocks.add(scriptMatcher.group(0));
}
result = scriptMatcher.replaceAll(tempScriptBlock);
// don't process inline css
Matcher styleMatcher = stylePattern.matcher(result);
while(styleMatcher.find()) {
styleBlocks.add(styleMatcher.group(0));
}
result = styleMatcher.replaceAll(tempStyleBlock);
//process pure html
result = processHtml(result);
//process preserved blocks
result = processPreBlocks(result, preBlocks);
result = processTextareaBlocks(result, taBlocks);
result = processScriptBlocks(result, scriptBlocks);
result = processStyleBlocks(result, styleBlocks);
result = processJspBlocks(result, jspBlocks);
preBlocks = taBlocks = scriptBlocks = styleBlocks = jspBlocks = null;
return result.trim();
}
private static String processHtml(String html) {
String result = html;
//remove comments
// if(removeComments) {
result = commentPattern.matcher(result).replaceAll("");
// }
//remove inter-tag spaces
// if(removeIntertagSpaces) {
result = itsPattern.matcher(result).replaceAll("><");
// }
//remove multi whitespace characters
// if(removeMultiSpaces) {
result = result.replaceAll("http://s{2,}"," ");
// }
return result;
}
private static String processJspBlocks(String html, List<String> blocks){
String result = html;
for(int i = 0; i < blocks.size(); i++) {
blocks.set(i, compressJsp(blocks.get(i)));
}
//put preserved blocks back
while(result.contains(tempJspBlock)) {
result = result.replaceFirst(tempJspBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
return result;
}
private static String processPreBlocks(String html, List<String> blocks) throws Exception {
String result = html;
//put preserved blocks back
while(result.contains(tempPreBlock)) {
result = result.replaceFirst(tempPreBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
return result;
}
private static String processTextareaBlocks(String html, List<String> blocks) throws Exception {
String result = html;
//put preserved blocks back
while(result.contains(tempTextAreaBlock)) {
result = result.replaceFirst(tempTextAreaBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
return result;
}
private static String processScriptBlocks(String html, List<String> blocks) throws Exception {
String result = html;
// if(compressJavaScript) {
for(int i = 0; i < blocks.size(); i++) {
blocks.set(i, compressJavaScript(blocks.get(i)));
}
// }
//put preserved blocks back
while(result.contains(tempScriptBlock)) {
result = result.replaceFirst(tempScriptBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
return result;
}
private static String processStyleBlocks(String html, List<String> blocks) throws Exception {
String result = html;
// if(compressCss) {
for(int i = 0; i < blocks.size(); i++) {
blocks.set(i, compressCssStyles(blocks.get(i)));
}
// }
//put preserved blocks back
while(result.contains(tempStyleBlock)) {
result = result.replaceFirst(tempStyleBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
return result;
}
private static String compressJsp(String source) {
//check if block is not empty
Matcher jspMatcher = jspPattern.matcher(source);
if(jspMatcher.find()) {
String result = compressJspJs(jspMatcher.group(1));
return (new StringBuilder(source.substring(0, jspMatcher.start(1))).append(result).append(source.substring(jspMatcher.end(1)))).toString();
} else {
return source;
}
}
private static String compressJavaScript(String source) {
//check if block is not empty
Matcher scriptMatcher = scriptPattern.matcher(source);
if(scriptMatcher.find()) {
String result = compressJspJs(scriptMatcher.group(1));
return (new StringBuilder(source.substring(0, scriptMatcher.start(1))).append(result).append(source.substring(scriptMatcher.end(1)))).toString();
} else {
return source;
}
}
private static String compressCssStyles(String source) {
//check if block is not empty
Matcher styleMatcher = stylePattern.matcher(source);
if(styleMatcher.find()) {
// 去掉注釋,換行
String result= multiCommentPattern.matcher(styleMatcher.group(1)).replaceAll("");
result = trimPattern.matcher(result).replaceAll("");
result = trimPattern2.matcher(result).replaceAll("");
return (new StringBuilder(source.substring(0, styleMatcher.start(1))).append(result).append(source.substring(styleMatcher.end(1)))).toString();
} else {
return source;
}
}
private static String compressJspJs(String source){
String result = source;
// 因注釋符合有可能出現(xiàn)在字符串中,所以要先把字符串中的特殊符好去掉
Matcher stringMatcher = stringPattern.matcher(result);
while(stringMatcher.find()){
String tmpStr = stringMatcher.group(0);
if(tmpStr.indexOf("http://") != -1 || tmpStr.indexOf("/*") != -1 || tmpStr.indexOf("*/") != -1){
String blockStr = tmpStr.replaceAll("http://", tempSingleCommentBlock).replaceAll("http:///*", tempMulitCommentBlock1)
.replaceAll("http://*/", tempMulitCommentBlock2);
result = result.replace(tmpStr, blockStr);
}
}
// 去掉注釋
result = signleCommentPattern.matcher(result).replaceAll("");
result = multiCommentPattern.matcher(result).replaceAll("");
result = trimPattern2.matcher(result).replaceAll("");
result = trimPattern.matcher(result).replaceAll(" ");
// 恢復(fù)替換掉的字符串
result = result.replaceAll(tempSingleCommentBlock, "http://").replaceAll(tempMulitCommentBlock1, "/*")
.replaceAll(tempMulitCommentBlock2, "*/");
return result;
}
}

使用注意事項(xiàng):

使用了上面方法后,再運(yùn)行程序,是不是發(fā)現(xiàn)每個(gè)頁(yè)面查看源代碼的時(shí)候都變成1行啦,還不錯(cuò)吧,但是在使用的時(shí)候還是要注意一些問(wèn)題:
1. 嵌入js本來(lái)想調(diào)用yuicompressor來(lái)壓縮,yuicompressor壓縮JS前,會(huì)先編譯js是否合法,因我們嵌入的js中可能很多會(huì)用到一些服務(wù)器端代碼,比如 var now = <%=DateTime.now %> ,這樣的代碼會(huì)編譯不通過(guò),所以無(wú)法使用yuicompressor。
最后只能自己寫(xiě)壓縮JS代碼,自己寫(xiě)的比較粗燥,所以有個(gè)問(wèn)題還解決,就是如果開(kāi)發(fā)人員在一句js代碼后面沒(méi)有加分號(hào)的話,壓縮成1行就很有可能出問(wèn)題。所以使用這個(gè)需要保證每條語(yǔ)句結(jié)束后都必須帶分號(hào)。

2. 因?yàn)槭窃诔绦騿?dòng)的時(shí)候壓縮所有jsp(ASPx),所以如果是用戶請(qǐng)求的時(shí)候動(dòng)態(tài)產(chǎn)生的html就無(wú)法壓縮。

JavaScript技術(shù)WEB高性能開(kāi)發(fā)之瘋狂的HTML壓縮,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 花蝴蝶在线高清视频观看免费播放 | 欧美极限变态扩张video | 99re6久久热在线视频 | 伊人亚洲AV久久无码精品 | 伊人久久国产免费观看视频 | 儿子操妈妈视频 | 久久亚洲精品AV无码四区 | 亚洲免费在线视频 | 奶头被客人吸得又红又肿 | 91精品福利一区二区 | 飘雪韩国在线观看免费高清完整版 | 亚洲第一页视频 | 大相蕉伊人狼人久草av | 扒开腿狂躁女人GIF动态图 | 国产午夜亚洲精品不卡电影 | 男人扒开添女人屁股 | 999久久狠狠免费精品 | 日韩经典欧美一区二区三区 | 青柠在线观看视频在线 | 97色伦在色在线播放 | 中文字幕在线不卡精品视频99 | 忘忧草在线影院WWW日本动漫 | 国产成人精视频在线观看免费 | 啊灬啊灬啊灬快灬深高潮啦 | 青青精品国产自在线拍 | 97久久国产露脸精品国产 | 最近中文字幕免费高清MV视频6 | 欧美日韩亚洲中字二区 | 91久久综合精品国产丝袜长腿 | 亚洲精品影院久久久久久 | 甜宠溺H宝贝嗯撞PLAY啊 | 丰满女友bd高清在线观看 | 麻豆精品传媒2021网站入口 | 人妻系列合集 | 成人精品视频网站 | 秋霞伦理电影在线看 | WWW国产亚洲精品久久麻豆 | 美女内射少妇三区五区 | 亚洲精品综合在线影院 | a视频免费在线 | 亚洲成年人影院 |