js在线压缩

添加评论 41 views 2010年6月25日

最近在看到[关注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代码处理的很简单.代码如下:

?View Code 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);
			}
		}
	}
  1. 2010年6月26日 at 09:29 | #1

    呵呵 今天回访你的网站 竟然发现你贴出了表扬信 :evil: 。太客气了。

  1. 还没有 trackbacks
订阅评论