2012-06-09 15 views
14

Der Versuch, gute Build-Umgebung für meine JS-Bibliothek vorzubereiten. Laut Bewertungen im Internet scheint UglifyJS eines der besten Kompressionsmodule zu sein, die unter NodeJS funktionieren. Hier ist also am besten empfohlene Weg, den Code von minifying:Uglify-js Variablennamen nicht fehlerhaft

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, pro.ast_mangle(ast) sollten Variablennamen mangeln, aber es funktioniert nicht. Alles, was ich aus dieser Pipe herausbekomme, ist JavaScript-Code, ohne Leerzeichen. Zuerst dachte ich, dass mein Code nicht für die Komprimierung optimiert war, aber dann versuchte ich es mit Google Closure und bekam eine ziemlich starke Komprimierung (mit verfälschten Variablennamen und allem).

UglifyJS Experten, irgendein Hinweis darauf, was ich falsch mache?

UPDATE:

Actual Code zu groß ist hier, zu verweisen aber auch ein Ausschnitt wie diese nicht verstümmelt bekommt:

;(function(window, document, undefined) { 

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

    // ... 

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

}(window, document)); 

Dies ist, was ich (nur Räume zu bekommen und beraubt Ich schätze):

+0

Ich denke, es würde helfen, wenn Sie ein kleines Code-Snippet und die Ergebnisse, mit denen Sie Probleme finden, veröffentlichen. –

+0

Ich dachte, vielleicht gab es eine Option, die mir fehlte. Jetzt mit dem kleinen Ausschnitt aktualisiert.Offensichtlich ist es etwas mit meiner Umgebung? .. Obwohl nicht sicher, wo zu debuggen es oder was könnte beeinflussen Uglify-js Fähigkeit zu mangeln, wenn es angefordert wird. – jayarjo

+1

Nun, über die Website von UglifyJS habe ich: '(Funktion (a, b, c) {Funktion d (a) {Rückgabetyp von a! =" Zeichenfolge "? A: b.getElementById (a)} a.mOxie = ao = d}) (Fenster, Dokument) 'Sind Sie sicher, dass Sie die richtigen Schalter eingeschaltet haben? –

Antwort

11

Ok, es scheint, dass die neueste Version von Uglify JS Mangle-Option explizit als wahr übergeben wird, sonst wird es nichts vermasseln. Wie folgt aus:

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 
8

Standardmäßig wird Uglify nicht Toplevel-Namen mangeln, vielleicht ist das, was Sie gesehen haben?

Versuchen Sie: -mt oder --mangle-Toplevel - mangle Namen in der Toplevel-Bereich zu (standardmäßig tun wir dies nicht).

+1

respektive ast = uglify.uglify.ast_mangle (ast, {Toplevel: true}); – axkibe

+1

Mein gesamter Code ist in eine anonyme selbstaufrufende Funktion gekapselt. Ich habe meine Frage mit einem Snippet aktualisiert. Und ein Hinweis darauf, wie ich die Situation debuggen könnte? – jayarjo

+1

Thx, funktioniert für mich –

0

Variablen im globalen Gültigkeitsbereich sind für jedes andere Skript verfügbar, so dass Uglify sie ohne speziellen Schalter nicht ändert, falls sie wirklich sichtbar sein müssen. Sie können entweder -mt/toplevel switch/setting verwenden, oder, noch besser, den umweltschädlichen globalen Bereich stoppen und klar anzeigen, dass Sie nicht beabsichtigen, dass diese Variablen außerhalb gesehen werden, sondern Ihren Code in eine anonyme selbstaufrufende Funktion einrahmen als privater Bereich dienen.

+0

"Ihren Code in anonyme selbstaufrufende Funktion einrahmen", das ist es, was ich tatsächlich tue. Nur ein Objekt der obersten Ebene wird angezeigt. – jayarjo

+1

Jede Variable in Ihrem Beispiel ist eine Variable aus dem äußeren, globalen Bereich. –

+1

Ja, Variablen aus dem äußeren Bereich werden in die selbstaufrufende anonyme Funktion als Argumente übergeben. Stellt sie das nicht für das Mangeln zur Verfügung (innerhalb der Funktion)? – jayarjo

1

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

Wenn Sie Uglify1 verwenden, ist es ein wenig komplizierter. Hier einige Code, den ich zusammen mit dem Code aus Uglify's squeeze_more.js file ändern:

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 über funktioniert nur auf dem globalen Funktionsaufrufen, aber es gibt Ihnen einen Rückruf, der ausgeführt wird, wenn die Wanderer einen Anruf an einem unbekannten finden (global) Methode.

Zum Beispiel angesichts der folgenden Eingabe:

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

er den Anruf bar(1) aber nichtbar(2) oder bar(3) finden würde.