Comment automatisez-vous la minification Javascript pour vos applications Web Java?

122

Je suis intéressé de savoir comment vous préférez automatiser la minification Javascript pour vos applications Web Java. Voici quelques aspects qui m'intéressent particulièrement:

  • Comment s'intègre- t-il ? Cela fait-il partie de votre outil de construction, d'un filtre de servlet, d'un programme autonome post-traitement du fichier WAR ou de quelque chose d'autre?
  • Est-ce facile à activer et à désactiver ? Ce n'est pas drôle d'essayer de déboguer un script minifié, mais il est également utile pour un développeur de pouvoir tester que la minification ne casse rien.
  • Fonctionne-t-il de manière transparente ou a-t-il des effets secondaires (en dehors de ceux inhérents à la minification) que je dois prendre en compte dans mon travail quotidien?
  • Quel minificateur utilise- t-il?
  • Manque- t-il des fonctionnalités auxquelles vous pouvez penser?
  • Qu'est-ce que vous aimez à ce sujet?
  • Qu'est - ce que tu n'aimes pas ?

Cela servira principalement de référence pour mes futurs projets (et j'espère que d'autres SOer le trouveront aussi informatif), donc toutes sortes d'outils sont intéressants.

(Notez que ce n'est pas une question de savoir quel minifier est le meilleur . Nous en avons déjà beaucoup.)

gustafc
la source
cela a l'air vraiment intéressant, je n'en ai pas entendu parler. Tous les outils que j'ai trouvés lors d'une recherche rapide sont des outils manuels qui ne s'exécutent qu'une seule fois. Ce serait bien s'il y avait un plug in pour fourmi ou maven. J'espère que quelqu'un a une bonne réponse.
Jay le
Et il semble que quelqu'un l'ait fait - vérifiez la réponse de dfa: stackoverflow.com/questions/1379856
...

Réponses:

65

Poste de résumé

Si vous publiez quelque chose de nouveau dans ce fil, modifiez ce message pour créer un lien vers le vôtre.

gustafc
la source
Les compresseurs minify-maven et maven yui ne fonctionnaient pas bien avec les fonctionnalités ES6 pour moi au moment de ce commentaire
DPM
13

Nous utilisons la tâche Ant pour réduire les fichiers js avec YUICompressor lors de la construction de la production et placer le résultat dans un dossier séparé. Ensuite, nous téléchargeons ces fichiers sur un serveur Web. Vous pouvez trouver de bons exemples d'intégration de YUI + Ant dans ce blog .

Voici un exemple:

<target name="js.minify" depends="js.preprocess">
    <apply executable="java" parallel="false">
        <fileset dir="." includes="foo.js, bar.js"/>
        <arg line="-jar"/>
        <arg path="yuicompressor.jar"/>
        <srcfile/>
        <arg line="-o"/>
        <mapper type="glob" from="*.js" to="*-min.js"/>
        <targetfile/>
    </apply>
</target>
serg
la source
2
Fragment; agréable. Reciblez-vous vos script srcbuilds on dev ou copiez-vous simplement des fichiers non minifiés dans le répertoire compressé / js?
gustafc le
Juste pour la production, téléchargez les fichiers compressés sur les originaux dans public_html / js. La bonne chose est qu'il n'y a pas de codage ou de changement de chemin entre le local et la production, le problème est que vous devez effectuer un téléchargement et un écrasement manuels (je suis sûr que cela peut être automatisé, mais pour nous, cela ne vaut pas la peine, le téléchargement quelques fichiers js de temps en temps ne sont pas trop importants).
serg
J'ai utilisé votre code mais il crée le fichier minifié à la racine de mon projet, je l'ai défini <fileset dir="${generatedScriptsDir}" includes="**/*.js"/>mais cela ne fonctionne pas. Comment puis-je générer le fichier dans le ${generatedScriptsDir}?
Vadorequest
essayez d'ajouter l'attribut «dir» à la balise «apply». assurez-vous que '$ {generatedScriptsDir}' a été créé en tant que 'propriété' avec la destination conçue
Rajasri.J
12

Je pense que l'un des meilleurs et des bons outils pour le travail est wro4j Consultez https://github.com/wro4j/wro4j

Il fait tout ce dont vous avez besoin:

  • Gardez les ressources Web du projet (js et css) bien organisées
  • Fusionnez-les et réduisez-les au moment de l'exécution (en utilisant un simple filtre) ou lors de la construction (en utilisant le plugin maven)
  • Gratuit et open source: publié sous une licence Apache 2.0
  • plusieurs outils de minification pris en charge par wro4j: JsMin, Google Closure compresseur, YUI, etc.
  • Utilisation très simple. Prend en charge le filtre de servlet, la configuration Java simple ou Spring
  • Prise en charge de JavaScript et CSS Meta Frameworks: CoffeeScript, Less, Sass, etc.
  • Validation: JSLint, CSSLint etc.

Peut fonctionner en mode débogage ainsi qu'en mode production. Spécifiez simplement tous les fichiers qu'il doit gérer / pré-traiter et il s'occupe du reste.

Vous pouvez simplement inclure des ressources fusionnées, minifiées et compressées comme ceci:

<script type="text/javascript" src="wro/all.js"></script>
SZ Quadri
la source
2
Semble en effet être un outil astucieux. Merci pour la mise à jour!
gustafc
Ajoute-t-il la gestion des versions aux fichiers de ressources pour forcer l'actualisation côté client? Je n'ai trouvé aucune documentation sur cette fonctionnalité.
Qiang
La seule chose qui me manque vraiment dans wro4j est le préfixeur css.
inafalcao
Est-il possible de diffuser du contenu statique (généré par un wroserveur d'applications) à partir d' apacheun serveur Web?
HybrisHelp
8

J'ai écrit des macros fourmis pour le compilateur Google Closure et le compresseur Yahoo et j'inclus ce fichier dans différents projets Web.

<?xml version="1.0" encoding="UTF-8"?>
<!-- CSS and JS minifier. -->
<!DOCTYPE project>
<project name="minifier" basedir=".">

  <property name="gc" value="compiler-r1592.jar" />
  <property name="yc" value="yuicompressor-2.4.6.jar" />

  <!-- Compress single js with Google Closure compiler -->
  <macrodef name="gc-js">
    <attribute name="dir" />
    <attribute name="src" />
    <sequential>
      <java jar="${gc}" fork="true">
        <!--
        - - compilation_level WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS
        Specifies the compilation level to use. Default: SIMPLE_OPTIMIZATIONS
        - - warning_level QUIET | DEFAULT | VERBOSE
        Specifies the warning level to use.
        -->
        <arg line="--js=@{dir}/@{src}.js" />
        <arg line="--js_output_file=@{dir}/@{src}-min-gc.js" />
      </java>
    </sequential>
  </macrodef>

  <!-- Compress single js with Yahoo compressor -->
  <macrodef name="yc-js">
    <attribute name="dir" />
    <attribute name="src" />
    <sequential>
      <java jar="${yc}" fork="true">
        <arg value="@{dir}/@{src}.js" />
        <arg line="-o" />
        <arg value="@{dir}/@{src}-min-yc.js" />
      </java>
    </sequential>
  </macrodef>

  <!-- Compress all js in directory with Yahoo compressor -->
  <macrodef name="yc-js-all">
    <attribute name="dir" />
    <sequential>
      <apply executable="java" parallel="false">
        <fileset dir="@{dir}" includes="*.js" excludes="*-min*.js" />
        <arg line="-jar" />
        <arg path="${yc}" />
        <srcfile />
        <arg line="-o" />
        <mapper type="glob" from="*.js" to="@{dir}/*-min-yc.js" />
        <targetfile />
      </apply>
    </sequential>
  </macrodef>

  <!-- Compress all css in directory with Yahoo compressor -->
  <macrodef name="yc-css-all">
    <attribute name="dir" default="${build.css.dir}" />
    <sequential>
      <apply executable="java" parallel="false">
        <fileset dir="@{dir}" includes="*.css" excludes="*-min*.css" />
        <arg line="-jar" />
        <arg path="${yc}" />
        <arg line="-v --line-break 0" />
        <srcfile />
        <arg line="-o" />
        <mapper type="glob" from="*.css" to="@{dir}/*-min.css" />
        <targetfile />
      </apply>
    </sequential>
  </macrodef>
</project>
  • Intégration: <import file="build-minifier.xml" />dans votre build.xml, puis invoquez comme d'habitude les tâches ant:<gc-js dir="${build.js.dir}" src="prototype" /> <yc-js-all dir="${build.js.dir}" />

  • Choix de deux minificateurs: compilateur Google Closure et compresseur Yahoo, vous devez les télécharger manuellement et les placer près du fichier xml

  • Les minificateurs ignorent les fichiers déjà compressés (se terminant par -min*)

  • Habituellement, je crée trois versions de script: non compressé (par exemple prototype.js) pour le débogage, compressé avec le compilateur de fermeture ( prototype-min-gc.js) pour le serveur de production, compressé avec Yahoo ( prototype-min-yc.js) pour le dépannage car le compilateur de fermeture utilise des optimisations risquées et produit parfois un fichier compressé invalide et le compresseur Yahoo est plus sûr

  • Le compresseur Yahoo peut minifier tous les fichiers dans un répertoire avec une seule macro, le compilateur de fermeture ne peut pas

Victor
la source
8

J'ai essayé deux façons:

  1. en utilisant un filtre de servlet. En mode production, le filtre est activé et il compresse toutes les données liées à une URL comme * .css ou * .js
  2. en utilisant maven et yuicompressor-maven-plugin ; la compression est effectuée à la volée (lors de l'assemblage de la guerre de production )

Bien sûr, cette dernière solution est meilleure car elle ne consomme pas de ressources au moment de l'exécution (mon application Web utilise le moteur d'application Google) et ne complique pas le code de votre application. Supposons donc ce dernier cas dans les réponses suivantes:

Comment s'intègre-t-il? Cela fait-il partie de votre outil de construction, d'un filtre de servlet, d'un programme autonome post-traitement du fichier WAR ou de quelque chose d'autre?

en utilisant maven

Est-ce facile à activer et à désactiver? Ce n'est pas drôle d'essayer de déboguer un script minifié, mais il est également utile pour un développeur de pouvoir tester que la minification ne casse rien.

vous ne l'activez que lors de l'assemblage de la guerre finale; en mode développement, vous voyez la version non compressée de vos ressources

Fonctionne-t-il de manière transparente ou a-t-il des effets secondaires (en dehors de ceux inhérents à la minification) que je dois prendre en compte dans mon travail quotidien?

absolument

Quel minificateur utilise-t-il?

Compresseur YUI

Manque-t-il des fonctionnalités auxquelles vous pouvez penser?

non, il est très complet et facile à utiliser

Qu'est-ce que vous aimez à ce sujet?

il est intégré à mon outil préféré (maven) et le plugin est dans le référentiel central (un bon citoyen maven)

dfa
la source
Plugin Maven - sympa. Dommage que mes projets actuels utilisent tous ant :)
gustafc
vous pouvez créer une cible qui construit un "fichier de guerre de production", en utilisant la tâche YUI ant
dfa
4

Je pense que vous avez besoin d'une bibliothèque de compression, par exemple une balise Granule.

http://code.google.com/p/granule/

Il gzip et combine des javascripts enveloppés par la balise g: compress en utilisant différentes méthodes, a également une tâche Ant

l'exemple de code est:

<g: compress>
  <script type = "text / javascript" src = "common.js" />
  <script type = "text / javascript" src = "fermeture / goog / base.js" />
  <script>
       goog.require ('goog.dom');
       goog.require ('goog.date');
       goog.require ('goog.ui.DatePicker');
  </script>
  <script type = "text / javascript">
      var dp = nouveau goog.ui.DatePicker ();
      dp.render (document.getElementById ('datepicker'));
  </script>
</ g: compresser>
...

Andy Bell
la source
Oui, ça a l'air plutôt chouette.
gustafc
3

Je suis vraiment surpris que personne n'ait mentionné JAWR - https://jawr.github.io

Il est assez mature et prend en charge toutes les fonctionnalités standard auxquelles on peut s'attendre, et un peu plus. Voici comment cela se compare aux excellents critères du PO.

Comment s'intègre-t-il? Cela fait-il partie de votre outil de construction, d'un filtre de servlet, d'un programme autonome post-traitement du fichier WAR ou de quelque chose d'autre?

Il effectuait à l'origine le traitement / le gros travail au démarrage de l'application et le service était basé sur un servlet . À partir de 3.x, ils ont ajouté la prise en charge de l' intégration au moment de la construction .

La prise en charge de JSP et Facelets est fournie via une bibliothèque de balises JSP personnalisée pour importer les ressources traitées. En plus de cela, un chargeur de ressources JS est implémenté qui prend en charge le chargement des ressources à partir de pages HTML statiques .

Est-ce facile à activer et à désactiver? Ce n'est pas drôle d'essayer de déboguer un script minifié, mais il est également utile pour un développeur de pouvoir tester que la minification ne casse rien.

Une debug=onoption peut être utilisée avant le démarrage de l'application et un GETparamètre personnalisé peut être spécifié lors de demandes individuelles en production pour basculer sélectivement en mode débogage au moment de l'exécution pour ladite demande.

Quel minificateur utilise-t-il?

Pour JS, il prend en charge YUI Compressor et JSMin, pour CSS je ne suis pas sûr.

Manque-t-il des fonctionnalités auxquelles vous pouvez penser?

SASSle soutien vient à l'esprit. Cela dit, il prend en charge LESS.

Amr Mostafa
la source
2

Notre projet l'a géré de plusieurs façons, mais nous avons continué à utiliser le compresseur YUI à travers nos différentes itérations.

Nous avions initialement un servlet qui gérait la compression pour JavaScript la première fois que ce fichier particulier était accédé; il a ensuite été mis en cache. Nous avions déjà un système en place pour gérer les fichiers de propriétés personnalisées, nous avons donc simplement mis à jour nos fichiers de configuration pour prendre en charge l'activation ou la désactivation du compresseur en fonction de l'environnement dans lequel nous travaillions.

Désormais, les environnements de développement n'utilisent jamais de JavaScript compressé à des fins de débogage. Au lieu de cela, nous gérons la compression dans notre processus de construction lors de l'exportation de notre application vers un fichier WAR.

Notre client n'a jamais soulevé de préoccupations concernant la compression et les développeurs ne le remarquent pas jusqu'à ce qu'ils décident de déboguer JavaScript. Je dirais donc que c'est plutôt transparent avec des effets secondaires minimes, voire inexistants.

doomspork
la source
Comment utilisez-vous le compresseur YUI à partir de votre processus de construction? Le plugin Maven ou autre chose?
gustafc
1
Désolé, nous utilisons actuellement Ant. Voici un lien utile pour la tâche Ant: blog.gomilko.com/2007/11/29/yui-compression-tool-as-ant-task
doomspork
1

Cela a fonctionné pour moi: https://bitbucket.org/m6_russell_francis/yui-compressor-ant-task/wiki/Home

<!-- minimize all static *.css & *.js content -->
<target name="static-content-minify">

    <taskdef name="yuicompressor"
             classname="com.metrosix.yuicompressor.anttask.YuiCompressorTask">
        <classpath>
            <pathelement location="${jar.yui.compressor}"/>
            <pathelement location="${jar.yui.anttask.compressor}" />
        </classpath>
    </taskdef>

    <yuicompressor todir="${build.static.content.min}" charset="utf-8" 
        preserveallsemicolons="true" munge="true" >
        <fileset dir="${src.static.content}">
            <include name="**/*.css"/>
            <include name="**/*.js"/>
        </fileset>
    </yuicompressor>
</target>
Tarzan inversé
la source
J'ai obtenu le $ {jar.yui.compressor} de search.maven.org: search.maven.org
Reverse Tarzan
1

J'écris un cadre de gestion des actifs Web, appelé humpty . Il vise à être plus simple et plus moderne que jawr ou wro4j en utilisant des WebJars et des ServiceLoaders.

Comment s'intègre-t-il? Cela fait-il partie de votre outil de construction, d'un filtre de servlet, d'un programme autonome post-traitement du fichier WAR ou de quelque chose d'autre?

En développement, un servlet traite les actifs selon les besoins. Les ressources seraient ensuite précompilées avant la production et placées dans un dossier public, de sorte que la seule partie utilisée soit la génération des inclusions correctes dans le HTML.

Est-ce facile à activer et à désactiver? Ce n'est pas drôle d'essayer de déboguer un script minifié, mais il est également utile pour un développeur de pouvoir tester que la minification ne casse rien.

Cela se ferait en basculant entre les modes de développement et de production.

Fonctionne-t-il de manière transparente ou a-t-il des effets secondaires (en dehors de ceux inhérents à la minification) que je dois prendre en compte dans mon travail quotidien?

Je pense que c'est transparent, mais favorise fortement l'utilisation des WebJars.

Quel minificateur utilise-t-il?

Quel que soit le plugin que vous mettez sur votre chemin de classe utilise. Je cherche actuellement à écrire un plugin pour le compilateur de fermeture Google.

Manque-t-il des fonctionnalités auxquelles vous pouvez penser?

Encore en pré-version, bien que je l'utilise en production. Le plugin maven a encore besoin de beaucoup de travail.

Qu'est-ce que vous aimez à ce sujet?

La simplicité de simplement ajouter une dépendance pour configurer le framework

Qu'est-ce que tu n'aimes pas?

C'est mon bébé, j'aime tout;)

Mwanji Ezana
la source
1

Vraiment en retard à la fête ici, mais j'ai pensé que cela pourrait aider quelqu'un à chercher encore une réponse différente:

Après avoir essayé d'utiliser YUI Compressor, j'ai été déçu qu'il soit incompatible avec les versions plus récentes de jQuery et Prism (les deux principales bibliothèques JS tierces dont j'avais besoin pour mon projet que je voulais compresser en un seul fichier). J'ai donc décidé d'utiliser Terser , qui est un fork d'Uglify-JS qui prend en charge ES6 +. Je n'ai pas pu l'exécuter directement à l'aide de la <exec>tâche, mais l'utilisation de la méthode de ligne de commande Windows fonctionne au moins pour Win 10 (sans dire que cela ne peut pas fonctionner autrement, mais c'était une solution de contournement très facile). Pas besoin d'ajouter quoi que ce soit d'autre à la variable système Path (car Node.JS est généralement ajouté lors de l'installation). J'utilise d'abord la <concat>tâche ANT pour créer un gros fichier non compressé. Utilisez <fileset>car cela préservera l'ordre (si c'est important, de toute façon).

<concat destfile="${js-big-file}" encoding="UTF-8" outputencoding="UTF-8" fixlastline="true">
   <filelist refid="js-input-filelist"/>
</concat>

Utilisez ensuite la <exec>tâche pour exécuter n'importe quel programme NPM, tel que Terser. La page de manuel Apache sur cette tâche a indiqué qu'il s'agissait de la solution de contournement Windows pour exécuter des fichiers .bat, mais elle vous permet vraiment d'exécuter à peu près n'importe quelle application de ligne de commande (même celles qui <exec>ne peuvent mystérieusement pas trouver le contraire).

<exec executable="cmd">
   <arg value="/c"/>
   <arg value="terser"/>
   <arg value="${js-big-file}" />
   <arg value="-o" />
   <arg value="${smaller-js-file}"/>  
</exec>

Intégrer? Il fait partie d'un script de construction ANT (un plugin DITA Open Toolkit pour prendre en charge JavaScript personnalisé, entre autres - pas une application Web Java en soi, mais utilisant Java pour créer une sortie HTML5), donc l'intégration n'était pas beaucoup plus que l'ajout de ceux-ci tâches vers une nouvelle cible (il y a plus de code concernant la définition des valeurs par défaut et la vérification des paramètres d'entrée!).

Facile à activer / désactiver? Dans mon cas, j'ai un paramètre que je passe à la construction ANT afin d'inclure la construction et la réduction du fichier JS. Donc oui, il n'effectue cette cible que si je règle le paramètre sur «Oui». C'est une chose assez facile à configurer dans une version ANT.

Transparent Jusqu'à présent, il semble n'avoir aucun effet sur l'un des nombreux fichiers JS que j'inclus. Certains d'entre eux sont les miens (et je ne suis en aucun cas un expert JS) et certains sont, comme je l'ai mentionné, des bibliothèques JS courantes.

Minifier Terser, mais vous pouvez utiliser à peu près n'importe quel minifié avec une entrée de ligne de commande avec cette méthode.

Manque de fonctionnalités? Terser fonctionne uniquement avec JavaScript. Si je veux faire la même chose pour mes fichiers CSS (ce que je fais), j'utilise YUI Compressor.

Comme ça, c'est un projet actuellement actif et bénéficie d'un bon support. De plus, l'implémentation actuelle (ne l'appelant que via la <exec>cible ANT ) me permet d'échanger des minificateurs si j'ai besoin d'utiliser autre chose plus tard.

Je n'aime pas que cela nécessite Node.JS. Rien contre Node.JS, remarquez, juste que ce projet particulier n'en ait pas besoin autrement. Je préfère de loin utiliser un fichier Java .jar comme YUI Compressor pour cela (je peux facilement le distribuer avec un plugin si j'en ai besoin).

Jason Coleman
la source
Les retardataires sont également les bienvenus! Je suis d'accord que c'est gênant d'avoir un projet dépendant de deux environnements de programmation différents (Java + Node). Pourtant, il n'est pas surprenant que la plupart des travaux Javascript se produisent dans la communauté Node, donc il n'y a pas grand-chose à faire à ce sujet, et Terser semble avoir beaucoup d'élan ces jours-ci. Merci pour votre contribution!
gustafc