js在线压缩
最近在看到[关注Java]给我的留言后,决定接受他的建议,对本站的js和css进行压缩.在此,对他的热情,表示由衷的感谢!在使用网上的在线压缩工具后,发现本站在ff浏览器下FireBug会提示js错误,很是郁闷.仔细研究之后发现,网上大多数的js压缩工具在压缩JavaScript代码后会省去部分语句后面的分号,导致浏览器不能正常解析JavaScript代码.
看下面截图,截图截自http://js.clicki.cc/.
观看什么压缩前的JavaScript代码,每个JavaScript语句后面都有个分号表示当前语句已经结束.
点击净化(压缩代码)按钮后,代码压缩如下:
var getPositionLite=function(el){var x=0,y=0;while(el){x+=el.offsetLeft||0;y+=el.offsetTop||0;el=el.offsetParent}return{x:x,y:y}};var history={‘v1.0′:['2009-08-07','代码美化功能上线'],’v1.1′:['2009-08-08','代码净化、压缩功能上线'],’v1.2′:['2009-08-09','代码解压功能上线'],’v1.21′:['2009-08-10','修正代码多次压缩后不能解压的bug'],’v1.22′:['2009-08-10','修正可能误解压的bug']};
按我的理解JavaScript代码在被压缩之后,应该可以用某些ide工具将其格式化成正常的代码,比如使用myeclipse工具.遗憾的是,在myeclipse工具中,按ctrl和shift和F按键后,代码不会格式化而且还会提示代码有错误!问题何在?
干脆还是用在线工具将代码美化一下,看看是啥样子.
从截图中看出,经过美化后的JavaScript代码有几行代码没有了分号,显然是被压缩工具给过滤掉了.而且被美化后的代码风格有点像json的风格.
在网上找了多个网站,经过测试后发现该网站的在线压缩工具能够达到我的预期期望与要求:http://zhongguoren.cn/jsmin/,你可以浏览本站的链接观看效果:[js在线压缩演示]
为什么该网站的压缩工具可以实现我想要的结果呢?看了看其中的源码,发现其中的JavaScript代码处理的很简单.代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | String.prototype.has = function(c) {
return this.indexOf(c) > -1;
};
function jsmin(comment, input, level) {
if (input === undefined) {
input = comment;
comment = '';
level = 2;
} else if (level === undefined || level < 1 || level > 3) {
level = 2;
}
if (comment.length > 0) {
comment += '\n';
}
var a = '', b = '', EOF = -1,
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
DIGITS = '0123456789', ALNUM = LETTERS
+ DIGITS + '_$\\', theLookahead = EOF;
function isAlphanum(c) {
return c != EOF && (ALNUM.has(c) || c.charCodeAt(0) > 126);
}
function get() {
var c = theLookahead;
if (get.i == get.l) {
return EOF;
}
theLookahead = EOF;
if (c == EOF) {
c = input.charAt(get.i);
++get.i;
}
if (c >= ' ' || c == '\n') {
return c;
}
if (c == '\r') {
return '\n';
}
return ' ';
}
get.i = 0;
get.l = input.length;
function peek() {
theLookahead = get();
return theLookahead;
}
function next() {
var c = get();
if (c == '/') {
switch (peek()) {
case '/':
for (;;) {
c = get();
if (c <= '\n') {
return c;
}
}
break;
case '*':
get();
for (;;) {
switch (get()) {
case '*':
if (peek() == '/') {
get();
return ' ';
}
break;
case EOF:
throw 'Error: Unterminated comment.';
}
}
break;
default:
return c;
}
}
return c;
}
function action(d) {
var r = [];
if (d == 1) {
r.push(a);
}
if (d < 3) {
a = b;
if (a == '\'' || a == '"') {
for (;;) {
r.push(a);
a = get();
if (a == b) {
break;
}
if (a <= '\n') {
throw 'Error: unterminated string literal: ' + a;
}
if (a == '\\') {
r.push(a);
a = get();
}
}
}
}
b = next();
if (b == '/' && '(,=:[!&|'.has(a)) {
r.push(a);
r.push(b);
for (;;) {
a = get();
if (a == '/') {
break;
} else if (a == '\\') {
r.push(a);
a = get();
} else if (a <= '\n') {
throw 'Error: unterminated Regular Expression literal';
}
r.push(a);
}
b = next();
}
return r.join('');
}
function m() {
var r = [];
a = '\n';
r.push(action(3));
while (a != EOF) {
switch (a) {
case ' ':
if (isAlphanum(b)) {
r.push(action(1));
} else {
r.push(action(2));
}
break;
case '\n':
switch (b) {
case '{':
case '[':
case '(':
case '+':
case '-':
r.push(action(1));
break;
case ' ':
r.push(action(3));
break;
default:
if (isAlphanum(b)) {
r.push(action(1));
} else {
if (level == 1 && b != '\n') {
r.push(action(1));
} else {
r.push(action(2));
}
}
}
break;
default:
switch (b) {
case ' ':
if (isAlphanum(a)) {
r.push(action(1));
break;
}
r.push(action(3));
break;
case '\n':
if (level == 1 && a != '\n') {
r.push(action(1));
} else {
switch (a) {
case '}':
case ']':
case ')':
case '+':
case '-':
case '"':
case '\'':
if (level == 3) {
r.push(action(3));
} else {
r.push(action(1));
}
break;
default:
if (isAlphanum(a)) {
r.push(action(1));
} else {
r.push(action(3));
}
}
}
break;
default:
r.push(action(1));
break;
}
}
}
return r.join('');
}
jsmin.oldSize = input.length;
ret = m(input);
jsmin.newSize = ret.length;
return comment + ret;
} |
上面代码的原理很简单,就是将要压缩的JavaScript代码中的空格换行制表符等空白空间给去掉,从而减少JavaScript代码的大小.
刚好最近在看json.jar源码,发现其中有个java类的代码与上面的方法在处理方式上有基本相同.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | public char nextClean() throws JSONException { for (;;) { char c = next(); if (c == '/') { switch (next()) { case '/': do { c = next(); } while (c != '\n' && c != '\r' && c != 0); break; case '*': for (;;) { c = next(); if (c == 0) { throw syntaxError("Unclosed comment"); } if (c == '*') { if (next() == '/') { break; } back(); } } break; default: back(); return '/'; } } else if (c == '#') { do { c = next(); } while (c != '\n' && c != '\r' && c != 0); } else if (c == 0 || c > ' ') { return c; } } } public String nextString(char quote) throws JSONException { char c; StringBuffer sb = new StringBuffer(); for (;;) { c = next(); switch (c) { case 0: case '\n': case '\r': throw syntaxError("Unterminated string"); case '\\': c = next(); switch (c) { case 'b': sb.append('\b'); break; case 't': sb.append('\t'); break; case 'n': sb.append('\n'); break; case 'f': sb.append('\f'); break; case 'r': sb.append('\r'); break; case 'u': sb.append((char) Integer.parseInt(next(4), 16)); break; case 'x': sb.append((char) Integer.parseInt(next(2), 16)); break; default: sb.append(c); } break; default: if (c == quote) { return sb.toString(); } sb.append(c); } } } |
呵呵 今天回访你的网站 竟然发现你贴出了表扬信
。太客气了。