尝试为我的js库准备好构建环境。根据网络上的评论UglifyJS似乎是最好的压缩模块之一,在NodeJS下工作。所以这里是推荐最小化代码的方法:
var jsp = require("uglify-js").parser;
var pro = require("uglify-js").uglify;
var orig_code = "... JS code here";
var ast = jsp.parse(orig_code); // parse code and get the initial AST
ast = pro.ast_mangle(ast); // get a new AST with mangled names
ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
var final_code = pro.gen_code(ast); // compressed code here
如此处所示,pro.ast_mangle(ast)
应该破坏变量名称,但事实并非如此。我从这个管道中得到的只是javascript代码,没有空格。起初我认为我的代码没有针对压缩进行优化,但后来我用Google Closure进行了尝试并得到了相当大的压缩(带有错误的变量名称和所有内容)。
UglifyJS专家,任何暗示我做错了什么?
更新:
实际代码太大而无法在此处引用,但即使是这样的代码段也不会被破坏:
;(function(window, document, undefined) {
function o(id) {
if (typeof id !== 'string') {
return id;
}
return document.getElementById(id);
}
// ...
/** @namespace */
window.mOxie = o;
}(window, document));
这就是我得到的(我想只有空格被剥离):
(function(window,document,undefined){function o(id){return typeof id!="string"?id:document.getElementById(id)}window.mOxie=window.o=o})(window,document)
答案 0 :(得分:15)
好吧,似乎最新版本的Uglify JS要求将mangle选项显式传递为true,否则它不会破坏任何东西。像这样:
var jsp = require("uglify-js").parser;
var pro = require("uglify-js").uglify;
var orig_code = "... JS code here";
var options = {
mangle: true
};
var ast = jsp.parse(orig_code); // parse code and get the initial AST
ast = pro.ast_mangle(ast, options); // get a new AST with mangled names
ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
var final_code = pro.gen_code(ast); // compressed code here
答案 1 :(得分:10)
默认情况下,uglify不会破坏顶级名称,也许这就是你所看到的?
尝试: -mt或--mangle-toplevel - 顶层范围内的mangle名称(默认情况下我们不这样做)。
答案 2 :(得分:1)
如果您使用的是Uglify2,则可以使用TopLevel.figure_out_scope()
。 http://lisperator.net/uglifyjs/scope
如果你使用的是Uglify1,那就有点复杂了。这是我通过修改Uglify's squeeze_more.js
file的代码放在一起的一些代码:
function eachGlobalFunctionCall(ast, callback) {
var w = uglify.uglify.ast_walker(),
walk = w.walk,
MAP = uglify.uglify.MAP,
scope;
function with_scope(s, cont) {
var save = scope, ret;
scope = s;
ret = cont();
scope = save;
return ret;
}
function _lambda(name, args, body) {
return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ];
}
w.with_walkers({
"function": _lambda,
"defun": _lambda,
"toplevel": function(body) {
return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];
},
"call": function(expr, args) {
var fnName = expr[1];
if (!scope.has(fnName)) { // <--- here's the important part
callback(fnName, args, scope);
}
}
}, function() {
return walk(uglify.uglify.ast_add_scope(ast));
});
}
上面的这个只适用于全局函数调用,但它会为你提供一个回调函数,当walker找到对未知(全局)方法的调用时执行该回调。
例如,给出以下输入:
function foo () {
bar(1);
(function () {
function bar() { }
bar(2);
(function () {
bar(3);
}());
}());
}
它会找到bar(1)
来电,但不是 bar(2)
或bar(3)
。
答案 3 :(得分:0)
全局范围内的变量可用于任何其他脚本,因此如果没有特殊的开关,Uglify将不会更改它们,以防您确实需要它们可见。您可以使用-mt
/ toplevel
切换/设置,或者更好地停止污染全局范围,并清楚地表明您不打算在外部看到这些变量,而是构建代码框架进入匿名自调用函数,作为私有范围。