it-swarm.com.de

Uglify-js manipuliert keine Variablennamen

Ich versuche, eine gute Build-Umgebung für meine js-Bibliothek vorzubereiten. Laut Rezensionen im Web UglifyJS scheint es eines der besten Kompressionsmodule zu sein, die unter NodeJS arbeiten. Daher empfiehlt es sich, den Code zu minimieren:

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

Wie hier zu sehen ist, sollte pro.ast_mangle(ast) Variablennamen zerstören, dies jedoch nicht. Alles, was ich aus dieser Pipe bekomme, ist Javascript-Code ohne Leerzeichen. Zuerst dachte ich, dass mein Code nicht für die Komprimierung optimiert wurde, aber dann habe ich es mit Google Closure ausprobiert und eine ziemlich Komprimierung erhalten (mit entstellten Variablennamen und allem). 

UglifyJS-Experten, ein Hinweis darauf, was ich falsch mache?

UPDATE:

Der eigentliche Code ist zu groß, um hier referenziert zu werden, aber selbst ein solcher Ausschnitt wird nicht verstümmelt:

;(function(window, document, undefined) {

    function o(id) {
        if (typeof id !== 'string') {
            return id;  
        }
        return document.getElementById(id);
    }   

    // ...

    /** @namespace */
    window.mOxie = o;

}(window, document));

Das ist was ich bekomme (ich denke mal, dass nur Leerzeichen entfernt werden):

(function(window,document,undefined){function o(id){return typeof id!="string"?id:document.getElementById(id)}window.mOxie=window.o=o})(window,document)
15
jayarjo

Ok, es scheint, dass die neueste Version von Uglify JS erfordert, dass die Option "Mangle" explizit als "true" übergeben wird, andernfalls wird nichts beeinträchtigt. So was:

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
14
jayarjo

Standardmäßig verwirrt uglify keine Toplevel-Namen. Vielleicht haben Sie das gesehen? 

Versuchen Sie es mit: - mt oder --mangle-toplevel - Namen auch im Toplevel-Bereich manipulieren (standardmäßig machen wir das nicht).

10
axkibe

Wenn Sie Uglify2 verwenden, können Sie TopLevel.figure_out_scope() verwenden. http://lisperator.net/uglifyjs/scope

Wenn Sie Uglify1 verwenden, ist es etwas komplizierter. Hier ist ein Code, den ich durch Ändern des Codes aus der Uglify's squeeze_more.js-Datei zusammengefügt habe: /:

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));
  });
}

Diese Funktion funktioniert nur bei globalen Funktionsaufrufen. Sie erhalten jedoch einen Rückruf, der ausgeführt wird, wenn der Walker einen Aufruf einer unbekannten (globalen) Methode findet.

Zum Beispiel die folgende Eingabe:

function foo () {
  bar(1);
  (function () {
    function bar() { }
    bar(2);
    (function () {
      bar(3);
    }());
  }());
}

Es würde den Aufruf bar(1) finden, aber nicht bar(2) oder bar(3).

1
nickf

Variablen im globalen Gültigkeitsbereich stehen für jedes andere Skript zur Verfügung, sodass Uglify sie ohne speziellen Schalter nicht ändert, falls sie wirklich sichtbar sein müssen. Sie können entweder -mt/toplevel Einstellung/verwenden, oder besser noch, den globalen Bereich nicht mehr verschmutzen und deutlich darauf hinweisen, dass diese Variablen nicht außerhalb angezeigt werden sollen, sondern Ihren Code in anonyme, selbstaufrufende Funktionen umrahmt als privater Bereich dienen.

0
Oleg V. Volkov