9 votes

Supprimer le code de débogage à l'intérieur d'une fonction en utilisant les optimisations simples du Closure Compiler

Je cherche un moyen de supprimer le code de débogage des fonctions afin de pouvoir ajouter des crochets de test aux fermetures. J'ai lu Google Closure Compiler avancé : supprimer les blocs de code au moment de la compilation et j'ai testé la suppression du code de débogage avec ce qui suit :

/** @define {boolean} */
var DEBUG = true;

if (DEBUG) {
    console.log('remove me');
}

Optimisation simple avec --define='DEBUG=false' réduit ce chiffre à var DEBUG=!1; . Il en va de même pour le présent document :

/** @const */
var DEBUG = false;

if (DEBUG) {
    console.log('remove me');
}

Là où je rencontre des difficultés, c'est lorsque j'utilise cette convention à l'intérieur d'une fonction :

/** @const */
var DEBUG = false;

function logMe() {
    if (DEBUG) {
        console.log('remove me');
    }
}

Cela revient à dire ce qui suit :

var DEBUG=!1;function logMe(){DEBUG&&console.log("remove me")};

Je m'attendrais à ce qu'il soit encore réduit à :

var DEBUG=!1;function logMe(){};

Y a-t-il une raison pour que cela ne fonctionne pas comme prévu ? Je cherche juste un moyen propre de déboguer le code et je ne suis pas prêt à me lancer dans des optimisations avancées.

Mise à jour

Conformément à la réponse de @John, j'ai implémenté mon propre compilateur et j'ai constaté que la configuration suivante permet de supprimer if (DEBUG) {} de l'intérieur et de l'extérieur du code dans le cas d'une @define :

CompilerOptions options = new CompilerOptions();
CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
//options.setInlineConstantVars(true);
options.setInlineVariables(CompilerOptions.Reach.ALL);
options.setDefineToBooleanLiteral("DEBUG", false);

Cela fonctionne assez bien pour un seul fichier avec les limitations suivantes :

  1. Pour ce faire, il faut var DEBUG doivent être définis dans chaque fichier, ce qui est une mauvaise pratique.
  2. Lorsque vous combinez plusieurs fichiers, vous ne pouvez avoir qu'un seul var DEBUG ou le compilateur ne peut pas l'optimiser. Cela pourrait être évité en compilant chaque fichier individuellement et en les fusionnant.
  3. La valeur étant définie au début du fichier, il n'est pas possible de recevoir la valeur à l'avance.

J'ai réfléchi à l'idée de supprimer toutes les var DEBUG à partir des fichiers et de l'injecter dans le source ou extern avant l'exécution, mais j'ai rencontré deux problèmes :

  • Le fait de le définir dans extern ne semble rien changer.
  • Non défini DEBUG dans le code non compilé provoque une erreur de référence dans le navigateur.

L'idéal serait de tester window.DEBUG ce qui ne provoque pas d'erreur de référence. Malheureusement, lors de l'injection de /** @const */ var window = {}; /** @const */ window.DEBUG = false; fonctionne au plus haut niveau, en réduisant if (window.DEBUG) {} l'optimisation est en fait annulée si elle est placée dans une fonction.

À moins qu'une autre option de compilateur ne fonctionne, la seule option qui aurait vraiment du sens serait d'opter pour window.DEBUG et avant la compilation injecter /** @const */ var DEBUG = false; et à un remplacement global de /\bwindow.DEBUG\b/ con DEBUG . Existe-t-il une meilleure solution ?

4voto

user2712511 Points 41

Utiliser l'annotation @define :

@define {boolean}

DEBUG = true ;

Et compiler avec l'option

--define="DEBUG=false"

3voto

John Points 3742

Une version personnalisée du compilateur vous permettrait de le faire. Vous souhaitez essentiellement "mettre en ligne des variables constantes" :

options.setInlineConstantVars(true) ;

Vous pouvez l'ajouter ici, dans applySafeCompilationOptions : http://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/javascript/jscomp/CompilationLevel.java?r=706

Vous pouvez également utiliser l'API Java et ajouter l'option (sans modifier le code du compilateur). Michael Bolin a donné un exemple de cette méthode ici :

http://blog.bolinfest.com/2009/11/calling-closure-compiler-from-java.html

2voto

FakeRainBrigand Points 12463

Il s'agit d'une ancienne réponse, mais j'ai trouvé un moyen qui n'est pas mentionné ici.

(function(){
    var DEBUG = true;

    if (DEBUG) {
        if (something === "wrong") {
            console.warn("Stop!  Hammer time!");
        }
        else if (something === "as expected") {
            console.log("All good :-)");
        }
    }

    foo();
})();

Avec ADVANCED_OPTIMIZATIONS, cela donne ceci :

"wrong" === something ? 
    console.warn("Stop!  Hammer time!") : 
    "as expected" === something && console.log("All good :-)");
foo();

Dans notre script de construction, nous pouvons réécrire la ligne DEBUG pour qu'elle devienne false ce qui donnerait le résultat suivant.

foo();

La raison en est que Closure supprime le code inaccessible. En créant la fermeture et en définissant une variable locale, Closure peut voir que nous ne pouvons pas faire quelque chose comme window.DEBUG === true Le code est donc assuré de ne jamais être exécuté.

1voto

Oleg V. Volkov Points 9724

Votre DEBUG est actuellement globale. GCC ne supprimera ni ne renommera les variables globales en mode d'optimisation simple, elles resteront donc disponibles pour tout code dans d'autres scripts qui pourraient vouloir y accéder. Essayez d'enfermer votre code dans une fonction anonyme.

1voto

steveinatorx Points 564

La façon dont j'ai résolu le problème de "supprimer les fonctions de débogage du javascript compilé par fermeture en utilisant SIMPLE_OPTIMIZATION" a été en combinant une méthode similaire à celle proposée par @John ainsi qu'en utilisant une partie de la mise à jour de @Brian Nichols. Je n'ai pu faire en sorte que le compilateur supprime les lignes qu'en plaçant ceci dans la portée globale de mon fichier js principal et en effectuant une compilation personnalisée (en utilisant plusieurs fichiers .js, cela les a quand même supprimées).

/** @const 
*   @type {boolean}
*/
var DEBUG = false;

//and used this format for my debug function
DEBUG && myLog('foo'); 

puis en compilant le compilateur de fermeture java avec ant pour inclure cette option options.setInlineVariables(CompilerOptions.Reach.ALL) ; sous la fonction applySafeCompilationOptions dans le fichier CompilationLevel.java comme le suggère @john. Cela a fonctionné pour moi et n'a pas cassé ma base de code comme l'a fait ADVANCED...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X