Y a-t-il un moyen de dire à Google Closure Compiler que * NOT * inline mes fonctions locales?

Voici ce que je recherche:

  • Je veux utiliser les fonctionnalités merveilleuses de la minification du mode SIMPLE tout en désactivant une seule fonction spécifique (désactiver la fonction locale en ligne).

  • MISE À JOUR: La réponse est NON, il n'est pas possible compte tenu de mon installation. Mais pour moi, il y a une solution car j'utilise Grails.
  • Comme @Chad a expliqué ci-dessous, "Cela viole les hypothèses principales du compilateur". Consultez mon UPDATE3 ci-dessous pour plus d'informations.


EN BREF:

  • J'utilise CompilationLevel.SIMPLE_OPTIMIZATIONS qui fait tout ce que je veux, sauf que cela implique mes fonctions locales.
  • Y a-t-il un moyen de contourner cela? Par exemple, existe-t-il un paramètre que je peux placer dans mes fichiers JS pour dire à Google Closure de ne pas intégrer mes fonctions locales?

Il serait cool d'avoir certaines directives au sommet de mon fichier javascript, telles que:

 // This is a JS comment... // google.closure.compiler = [inlineLocalFunctions: false] 

Je développe une application Grails et j'utilise le plugin asset-pipeline de Grails , qui utilise Google Closure Compiler (ci-après Compiler). Le plugin prend en charge les différents niveaux de minification que Compiler prend en charge via Grails config grails.assets.minifyOptions . Cela permet 'SIMPLE', 'AVANCÉ', 'WHITESPACE_ONLY'.

AssetCompiler.groovy (plugin asset-pipeline) appelle ClosureCompilerProcessor.process()

Cela affecte éventuellement SIMPLE_OPTIMIZATIONS sur l'objet CompilerOptions. Et ce faisant, CompilerOptions.inlineLocalFunctions = true comme sous-produit (c'est un comportement codé dur dans Compiler). Si je WHITESPACE_ONLY utiliser WHITESPACE_ONLY le résultat serait inlineLocalFunctions=false .

Ainsi, en utilisant le paramètre "SIMPLE" d'Asset Pipeline, les fonctions locales sont en cours et cela me cause des problèmes. Exemple: ExtJS ext-all-debug.js qui utilise beaucoup de fonctions locales.

SO post Est-il possible de faire de Google Closure compilateur * pas * en ligne certaines fonctions? Fournit de l'aide. Je peux utiliser sa window['dontBlowMeAway'] = dontBlowMeAway truc de window['dontBlowMeAway'] = dontBlowMeAway pour empêcher mes fonctions de s'installer. Cependant, j'ai beaucoup de fonctions et je ne suis pas sur le point de faire cela manuellement pour chacun d'eux; Je ne voudrais pas non plus écrire un script pour le faire pour moi. Créer un modèle JS et essayer d'identifier les fonctions locales ne semble pas sécurisé, amusant ni rapide.

Le message de SO précédent dirige le lecteur vers https://developers.google.com/closure/compiler/docs/apititory%C3%A9n%C3%A9n%C3%A9nel , où l'astuce window['bla'] est expliquée, et ça marche.

Wow merci d'avoir lu ce long.

Aidez-moi? 🙂


UPDATE1:

D'accord. Tout en dépensant tous les efforts pour écrire cette question, je pourrais avoir une astuce qui pourrait fonctionner. Grails utilise Groovy. Groovy rend l'interception d'appel de méthode facile en utilisant son MetaClass API.

Je vais essayer d'intercepter l'appel à:

 com.google.javascript.jscomp.Compiler.compile( List<T1> externs, List<T2> inputs, CompilerOptions options) 

Ma méthode d'interception ressemblera à:

 options.inlineLocalFunctions=false // Then delegate call to the real compile() method 

C'est l'heure du coucher, alors je vais devoir essayer cela plus tard. Même ainsi, il serait bon de résoudre ce problème sans un piratage.


UPDATE2: La réponse dans une publication similaire ( Est-il possible de faire le compilateur Google Closure * pas * en ligne certaines fonctions? ) Ne résout pas mon problème en raison de la grande quantité de fonctions dont j'ai besoin en ligne. J'ai déjà expliqué ce point.

Prenez le fichier ExtJS que j'ai cité ci-dessus comme exemple de la raison pour laquelle la publication SO similaire ci-dessus ne résout pas mon problème. Regardez le code brut pour ext-all-debug.js . Trouvez la fonction byAttribute (). Ensuite, continuez à chercher la chaîne "byAttribute" et vous verrez que cela fait partie des chaînes définies. Je ne suis pas familier avec ce code, mais je supposer que ces valeurs basées sur les byAttribute de byAttribute sont ensuite transmises à la fonction eval () de JS pour l'exécution. Le compilateur ne modifie pas ces valeurs de byAttribute lorsqu'il fait partie d'une chaîne. Une fois la function byAttribute est function byAttribute , les tentatives d'appel de la fonction ne sont plus possibles.


UPDATE3: J'ai essayé deux stratégies pour résoudre ce problème et les deux ont échoué. Cependant, j'ai réussi à mettre en œuvre une solution de contournement. Mes tentatives échouées:

  1. Utilisez l'interception de la méthode Groovy (Meta Object Protocol, alias MOP) pour intercepter com.google.javascript.jscomp.Compiler.compile() .
  2. Fork the closure-compiler.jar (faites ma propre copie personnalisée) et modifiez com.google.javascript.jscomp.applySafeCompilationOptions() en définissant options.setInlineFunctions(Reach.NONE); Au lieu de LOCAL.

L'interception de méthode ne fonctionne pas car Compiler.compile() est une classe Java qui est invoquée par une classe Groovy marquée comme @CompileStatic . Cela signifie que la MOP de Groovy n'est pas utilisée lorsque process() appelle le Compiler.compile() de Google Compiler.compile() . Même ClosureCompilerProcessor.translateMinifyOptions() (code Groovy) ne peut pas être intercepté car la classe est @CompileStatic . La seule méthode pouvant être interceptée est ClosureCompilerProcessor.process() .

Forking Google-closing-compiler.jar était ma dernière station feinte. Mais juste comme @Chad dit ci-dessous, il suffit d'insérer options.setInlineFunctions(Reach.NONE) au bon endroit, ne ressuscitais pas mes noms de fonctions JS en ligne. J'ai essayé de proposer d'autres options telles que setRemoveDeadCode=false en vain. Je me suis rendu compte de ce que le Tchad a dit avoir raison. Je finirais par basculer les paramètres et détruire probablement la façon dont fonctionne la minification.

Ma solution: j'ai pré compressé ext-all-debug.js avec UglifyJS et les ai ajoutés à mon projet. Je pourrais avoir nommé les fichiers ext-all-debug.min.js pour le faire plus proprement mais je n'ai pas. Voici les paramètres que j'ai placés dans mon Grails Config.groovy:

 grails.assets.minifyOptions = [ optimizationLevel: 'SIMPLE' // WHITESPACE_ONLY, SIMPLE or ADVANCED ] grails.assets.minifyOptions.excludes = [ '**ext-all-debug.js', '**ext-theme-neptune.js' ] 

Terminé. Problème résolu.

Mots-clés: minify, minification, uglify, UglifyJS, UglifyJS2

Dans ce cas, vous devriez faire une compilation personnalisée du compilateur ou utiliser l'API Java.

Cependant, l'inactivité invalidante n'est pas suffisante pour que cela soit sécurisé. Le renommage et l'élimination du code mort provoqueront également des problèmes. Cela viole les hypothèses fondamentales du compilateur. Cette fonction locale est SEULEMENT référencée à partir de chaînes.

Ce code est uniquement sécurisé pour le mode WHITESPACE_ONLY du compilateur.