2012-06-09 33 views
14

Tentativo di preparare un buon ambiente di compilazione per la mia libreria js. Secondo le recensioni sul web, lo UglifyJS sembra essere uno dei migliori moduli di compressione in circolazione, funzionante con NodeJS. Così qui è migliore metodo consigliato di Minimizzando le code:Uglify-js non altera i nomi delle variabili

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 

Come si è visto qui, pro.ast_mangle(ast) dovrebbe storpiare i nomi delle variabili, ma non è così. Tutto quello che ottengo da questo pipe è il codice javascript, senza spazi. All'inizio pensavo che il mio codice non fosse ottimizzato per la compressione, ma poi l'ho provato con Google Closure e ottenuto una discreta compressione (con nomi di variabili storpiati e tutto il resto).

UglifyJS esperti, qualche suggerimento su ciò che sto facendo male?

UPDATE:

codice effettivo è troppo grande per fare riferimento qui, ma anche un frammento come questo non ottiene straziati:

;(function(window, document, undefined) { 

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

    // ... 

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

}(window, document)); 

Questo è ciò che ottengo (solo spazi vengono spogliati Immagino):

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

Penso che sarebbe d'aiuto se pubblichi un piccolo cicalino di codice e i risultati con i quali trovi problemi. –

+0

Ho pensato che forse c'era qualche opzione che mi mancava. Aggiornato ora con il piccolo frammento.Ovviamente è qualcosa con il mio ambiente? .. Anche se non sono sicuro da dove iniziare il debugging o cosa potrebbe influenzare la capacità di uglify-js di manipolare, quando richiesto. – jayarjo

+1

Bene, tramite il sito Web di UglifyJS, ho ottenuto: '(funzione (a, b, c) {funzione d (a) {return typeof a! =" Stringa "? A: b.getElementById (a)} a.mOxie = ao = d}) (finestra, documento) 'Sei sicuro di aver attivato gli interruttori giusti? –

risposta

11

Ok, sembra che l'ultima versione di Uglify JS richieda che l'opzione mangle sia passata esplicitamente come vera, altrimenti non mancherà nulla. Come questo:

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

Di default uglify non mangerà nomi di livello superiore, forse è quello che hai visto?

Prova: -MT o --mangle-toplevel - nomi mangano del perimetro toplevel troppo (per default non facciamo questo).

+1

rispettivamente ast = uglify.uglify.ast_mangle (ast, {toplevel: true}); – axkibe

+1

Tutto il mio codice è incapsulato in una funzione anonima di auto-invocazione. Ho aggiornato la mia domanda con uno snippet. E un accenno a come potrei fare il debug della situazione? – jayarjo

+1

Thx, funziona per me –

0

Le variabili in ambito globale sono disponibili per qualsiasi altro script, quindi Uglify non le cambierà senza uno switch speciale, nel caso in cui sia davvero necessario che siano visibili. È possibile utilizzare lo switch/impostazione -mt/toplevel o, meglio ancora, arrestare l'ambito globale di inquinamento e indicare chiaramente che non si intende che tali variabili vengano visualizzate all'esterno, ma inquadrando il codice in una funzione di auto-richiamo anonimo che servire come ambito privato.

+0

"Framing your code into anonimo self-invoking function" è quello che faccio in realtà. È esposto solo un oggetto di livello superiore. – jayarjo

+1

Ogni variabile nell'esempio è una variabile dall'ambito globale esterno. –

+1

Sì, le variabili dall'ambito esterno vengono passate alla funzione anonima auto-invocante come argomenti. Questo non li rende disponibili per il mangling (all'interno della funzione)? – jayarjo

1

Se stai usando Uglify2, è possibile utilizzare TopLevel.figure_out_scope(). http://lisperator.net/uglifyjs/scope

Se si utilizza Uglify1, è un po 'più complicato. Ecco alcuni codice che ho messo insieme modificando il codice da 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)); 
    }); 
} 

Questo uno sopra funziona solo su chiamate di funzione a livello mondiale, ma ti dà una funzione di callback che viene eseguito come l'escursionista trova una chiamata a uno sconosciuto (globale) metodo.

Ad esempio, dato il seguente testo:

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

Sarebbe trovare la chiamata bar(1) ma nonbar(2) o bar(3).

Problemi correlati