>  기사  >  웹 프론트엔드  >  고성능 WEB 개발을 위한 놀라운 HTML 압축_javascript 기술

고성능 WEB 개발을 위한 놀라운 HTML 압축_javascript 기술

WBOY
WBOY원래의
2016-05-16 18:24:571007검색

일반적으로 gzip을 시작할 때 현재 html은 동적이고 브라우저 캐시를 사용하지 않기 때문에 html에 대해 gzip을 거의 시작하지 않습니다. gzip이 활성화되면 각 요청을 압축해야 하며 이로 인해 더 많은 서버 리소스가 소비되고 js 및 시작됩니다. css.js와 CSS 모두 캐싱을 사용하므로 Gzip이 더 좋습니다. 개인적으로 HTML 압축의 가장 큰 장점은 돈을 많이 벌 수 있다는 점이라고 생각합니다. 한 번만 작성하면 추가 개발 작업을 추가하지 않고도 향후 모든 프로그램에서 사용할 수 있습니다.
"JS와 CSS의 병합, 압축, 캐시 관리" 기사에서 JS와 CSS를 자동으로 병합, 압축하고 버전 번호를 추가하는 내가 작성한 구성 요소를 언급했습니다. 이번에는 html을 압축하는 기능도 이 구성 요소에 추가되었습니다. 즉, 프로그램이 시작될 때(contextInitialized 또는 Application_Start) 압축을 위해 모든 html 및 jsp(aspx)를 검색하는 과정이 매우 간단합니다.
압축 참고 사항:
구현 방법은 주로 정규식을 사용하여 검색하고 바꾸는 것입니다. HTML을 압축할 때 주로 다음 사항에 주의해야 합니다.
1. pre, textarea 태그의 콘텐츠 형식을 유지해야 하며 압축할 수 없습니다.
2. HTML 주석을 제거할 때 다음과 같은 일부 주석은 제거할 수 없습니다: . 포함된 js에서 주석을 압축할 때 주의하세요. 주석 기호가 문자열에 나타날 수 있기 때문입니다. 예: var url = "http://www.cnblogs.com" // 위의 // 주석은 아닙니다.
JS 줄 바꿈을 제거하는 경우 작업 내용을 직접 따를 수 없습니다. 다음 코드를 고려하세요.
else
return; 공백이 없으면 elsereturn이 됩니다.
4. jsp(aspx)에서는 일부 서버 코드를 삽입하는 데 사용될 가능성이 매우 높습니다. 이때 내부 주석 처리 방법도 별도로 필요합니다. js와 동일합니다.
소스 코드:
다음은 Java 구현의 소스 코드입니다. 여기를 클릭하면 코드를 다운로드할 수 있으며 누구나 쉽게 넷 코드로 변경할 수 있습니다.


코드 복사 코드는 다음과 같습니다.

import java.io.StringReader;
java.io.StringWriter 가져오기;
java.util.* 가져오기;
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&&&";
비공개 정적 문자열 tempTextAreaBlock = "%%%HTMLCOMPRESS~TEXTAREA&&&";
private static String tempScriptBlock = "%%%HTMLCOMPRESS~SCRIPT&&&";
private static String tempStyleBlock = "%%%HTMLCOMPRESS~STYLE&&&";
private static String tempJspBlock = "%%%HTMLCOMPRESS~JSP&&&";
비공개 정적 패턴 commentPattern = Pattern.compile("", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 itsPattern = Pattern.compile(">\s ?<", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 prePattern = Pattern.compile("]*?>.*?", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 taPattern = Pattern.compile("]*?>.*?", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 jspPattern = Pattern.compile("<%([^-@][\w\W]*?)%>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
// <스크립트>
비공개 정적 패턴 scriptPattern = Pattern.compile("(?:|", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
비공개 정적 패턴 stylePattern = Pattern.compile("()]*?>(. )", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
// 单行注释,
private static Pattern signleCommentPattern = Pattern.compile("//.*");
// 字符串匹配
private static Pattern stringPattern = Pattern.compile("("[^"\n]*?"|'[^'\n]*?')");
// 트리밍 작업 공간
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);
private static String tempSingleCommentBlock = "%%%HTMLCOMPRESS~SINGLECOMMENT&&&" // //位符
private static String tempMulitCommentBlock1 = "%%%HTMLCOMPRESS~MULITCOMMENT1&&&" // /*符
private static String tempMulitCommentBlock2 = "%%%HTMLCOMPRESS~MULITCOMMENT2&&&" // */·位符

public static String 압축(String html)에서 예외 발생 {
if(html == null || html.length() == 0) {
return html;
List preBlocks = new ArrayList(); 배열목록()
목록 scriptBlocks = new ArrayList();
목록 styleBlocks = new ArrayList();
목록 jspBlocks = new ArrayList();
문자열 결과 = html;
//인라인 자바 코드 유지
Matcher jspMatcher = jspPattern.matcher(result);
while(jspMatcher.find()) {
jspBlocks.add(jspMatcher.group(0));
}
결과 = jspMatcher.replaceAll(tempJspBlock);
//PRE 태그 유지
Matcher preMatcher = prePattern.matcher(result);
while(preMatcher.find()) {
preBlocks.add(preMatcher.group(0));
}
결과 = preMatcher.replaceAll(tempPreBlock);
//TEXTAREA 태그 유지
Matcher taMatcher = taPattern.matcher(result);
while(taMatcher.find()) {
taBlocks.add(taMatcher.group(0));
}
결과 = taMatcher.replaceAll(tempTextAreaBlock);
//SCRIPT 태그 유지
Matcher scriptMatcher = scriptPattern.matcher(result);
while(scriptMatcher.find()) {
scriptBlocks.add(scriptMatcher.group(0));
}
결과 = scriptMatcher.replaceAll(tempScriptBlock);
// 인라인 CSS를 처리하지 않음
Matcher styleMatcher = stylePattern.matcher(result);
while(styleMatcher.find()) {
styleBlocks.add(styleMatcher.group(0));
}
결과 = styleMatcher.replaceAll(tempStyleBlock);
//순수 HTML 처리
result = processHtml(result);
//보존된 블록 처리
result = processPreBlocks(result, preBlocks);
결과 = processTextareaBlocks(결과, taBlocks);
결과 = processScriptBlocks(결과, scriptBlocks);
결과 = processStyleBlocks(결과, styleBlocks);
결과 = processJspBlocks(결과, jspBlocks);
preBlocks = taBlocks = scriptBlocks = styleBlocks = jspBlocks = null;
결과 반환.trim();
}
private static String processHtml(String html) {
String result = html;
//댓글 제거
// if(removeComments) {
result = commentPattern.matcher(result).replaceAll("");
// }
//태그 간 공백 제거
// if(removeIntertagSpaces) {
result = itsPattern.matcher(result).replaceAll("><");
// }
//여러 공백 문자 제거
// if(removeMultiSpaces) {
result = result.replaceAll("\s{2,}"," ");
// }
결과 반환;
}
private static String processJspBlocks(String html, List 블록){
String result = html;
for(int i = 0; i blocks.set(i,compressJsp(blocks.get(i)));
}
//보존된 블록을 다시 넣기
while(result.contains(tempJspBlock)) {
result = result.replaceFirst(tempJspBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
결과 반환;
}
비공개 정적 문자열 processPreBlocks(String html, List 블록)에서 예외 발생 {
String result = html;
//보존된 블록을 다시 넣기
while(result.contains(tempPreBlock)) {
result = result.replaceFirst(tempPreBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
결과 반환;
}
비공개 정적 문자열 processTextareaBlocks(String html, List 블록)에서 예외 발생 {
String result = html;
//보존된 블록을 다시 넣기
while(result.contains(tempTextAreaBlock)) {
result = result.replaceFirst(tempTextAreaBlock, Matcher.quoteReplacement(blocks.remove(0)));
}
결과 반환;
}
비공개 정적 문자열 processScriptBlocks(String html, List 블록)에서 예외 발생 {
String result = html;
// if(compressJavaScript) {
for(int i = 0; i blocks.set(i,compressJavaScript(blocks.get(i)) );
}
// }
//보존된 블록을 다시 넣기
while(result.contains(tempScriptBlock)) {
result = result.replaceFirst(tempScriptBlock, Matcher.quoteReplacement(blocks.remove) (0)));
}
결과 반환;
}
비공개 정적 문자열 processStyleBlocks(String html, List 블록)에서 예외 발생 {
String result = html;
// if(compressCss) {
for(int i = 0; i blocks.set(i,compressCssStyles(blocks.get(i)) );
}
// }
//보존된 블록을 다시 넣기
while(result.contains(tempStyleBlock)) {
result = result.replaceFirst(tempStyleBlock, Matcher.quoteReplacement(blocks.remove) (0)));
}
결과 반환;
}
private static String 압축Jsp(String source) {
//블록이 비어 있지 않은지 확인
Matcher jspMatcher = jspPattern.matcher(source);
if(jspMatcher.find()) {
String result = 압축JspJs(jspMatcher.group(1));
return (new StringBuilder(source.substring(0, jspMatcher.start(1))).append(result).append(source.substring(jspMatcher.end(1)))).toString();
} else {
반환 소스;
}
}
private static String 압축JavaScript(String source) {
//블록이 비어 있지 않은지 확인
Matcher scriptMatcher = scriptPattern.matcher(source);
if(scriptMatcher.find()) {
String result = 압축JspJs(scriptMatcher.group(1));
return (new StringBuilder(source.substring(0, scriptMatcher.start(1))).append(result).append(source.substring(scriptMatcher.end(1)))).toString();
} else {
반환 소스;
}
}
private static String 압축CssStyles(String source) {
//블록이 비어 있지 않은지 확인
Matcher styleMatcher = stylePattern.matcher(source);
if(styleMatcher.find()) {
// 去掉注释,换行
String result= multiCommentPattern.matcher(styleMatcher.group(1)).replaceAll("");
결과 = TrimPattern.matcher(result).replaceAll("");
결과 = TrimPattern2.matcher(result).replaceAll("");
return (new StringBuilder(source.substring(0, styleMatcher.start(1))).append(result).append(source.substring(styleMatcher.end(1)))).toString();
} else {
반환 소스;
}
}
private static String extractJspJs(String source){
String result = source;
// 문자열에 주석이 나타날 수 있으므로 문자열의 특수 문자를 먼저 제거해야 합니다
Matcher stringMatcher = stringPattern. matcher(result);
while(stringMatcher.find()){
String tmpStr = stringMatcher.group(0)
if(tmpStr.indexOf("//") != -1 || tmpStr.indexOf("/*") != -1 || tmpStr.indexOf("*/") != -1){
String blockStr = tmpStr.replaceAll("//" , tempSingleCommentBlock).replaceAll( "/\*", tempMulitCommentBlock1)
.replaceAll("\*/", 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(" ");
// 대체된 문자열 복원
result = result.replaceAll( tempSingleCommentBlock, "//") .replaceAll(tempMulitCommentBlock1, "/*")
.replaceAll(tempMulitCommentBlock2, "*/");
return result;
}
}

사용 시 참고 사항 :

위 방법을 사용하고 프로그램을 실행한 후, 각 페이지의 소스코드를 보면 1줄로 되어있는데, 사용해보면 그래도 비용을 지불해야 하는 경우가 있나요? 몇 가지 문제에 주의:
1. js를 삽입할 때 원래 yuicompressor를 호출하여 JS를 압축하려고 했습니다. 먼저 js를 컴파일하여 합법적인지 확인합니다. embed는 var now = <%=DateTime.now %>와 같은 일부 서버측 코드를 사용할 수 있으며, 이러한 코드는 컴파일에 실패하므로 yuicompressor를 사용할 수 없습니다.
결국 압축된 JS 코드를 제가 직접 작성해야 했습니다. 제 글이 상대적으로 거칠어서 아직 해결해야 할 문제가 있습니다. 즉, 개발자가 js 코드 문장 뒤에 세미콜론을 추가하지 않으면, 압축된 JS 코드가 한 줄의 질문으로 압축될 가능성이 매우 높습니다. 따라서 이것을 사용할 때 각 명령문 끝에 세미콜론이 있어야 함을 확인해야 합니다.

2. 프로그램 시작 시 모든 jsp(aspx)가 압축되기 때문에 동적으로 생성된 html은 사용자가 요청할 때 압축될 수 없습니다.
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
이전 기사:JQuery 대화 상자 메모리 누수 문제다음 기사:JQuery 대화 상자 메모리 누수 문제

관련 기사

더보기