繁体   English   中英

Uglify-js不会破坏变量名称

[英]Uglify-js doesn't mangle variable names

试图为我的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)

好吧,似乎最新版本的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

默认情况下,uglify不会破坏顶级名称,也许这就是你所看到的?

尝试:-mt或--mangle-toplevel - 顶层范围内的mangle名称(默认情况下我们不这样做)。

如果您使用的是Uglify2,则可以使用TopLevel.figure_out_scope() http://lisperator.net/uglifyjs/scope

如果你使用的是Uglify1,那就有点复杂了。 这是我通过修改Uglify的squeeze_more.js文件中的代码放在一起的一些代码:

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)

全局范围内的变量可用于任何其他脚本,因此如果没有特殊的开关,Uglify将不会更改它们,以防您确实需要它们可见。 您可以使用-mt / toplevel切换/设置,或者更好地停止污染全局范围并清楚地表明您不打算在外部看到这些变量,而是将代码框架化为匿名自调用函数将作为私人范围。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM