Come automatizzi la minificazione Javascript per le tue applicazioni web Java?


122

Mi interessa sapere come preferisci automatizzare la minificazione Javascript per le tue app web Java. Ecco alcuni aspetti che mi interessano particolarmente:

  • Come si integra? Fa parte del tuo strumento di compilazione, di un filtro servlet, di un programma autonomo che esegue la post-elaborazione del file WAR o di qualcos'altro?
  • È facile da abilitare e disabilitare ? Non è molto divertente provare a eseguire il debug di uno script minimizzato, ma è anche utile per uno sviluppatore essere in grado di verificare che la minificazione non interrompa nulla.
  • Funziona in modo trasparente o ha effetti collaterali (a parte quelli inerenti alla minificazione) che devo considerare nel mio lavoro quotidiano?
  • Quale minifier usa?
  • Manca qualche caratteristica a cui puoi pensare?
  • Cosa ti piace di questo?
  • Cosa non ti piace di questo?

Questo servirà principalmente come riferimento per i miei progetti futuri (e spero che anche altri SO lo troveranno informativo), quindi tutti i tipi di strumenti sono interessanti.

(Nota che questa non è una domanda su quale minifier sia il migliore . Ne abbiamo già molti in giro).


questo sembra davvero interessante, non ne avevo sentito parlare. Tutti gli strumenti che ho trovato in una ricerca rapida sono strumenti manuali che vengono eseguiti una volta. Sarebbe bello se ci fosse un plug in per ant o maven. Si spera che qualcuno abbia una buona risposta.
Jay,

E sembra che qualcuno ha fatto - verificare di DFA risposta: stackoverflow.com/questions/1379856/...
gustafc

Risposte:


65

13

Stiamo usando Ant task per minimizzare i file js con YUICompressor durante la build di produzione e mettere il risultato in una cartella separata. Quindi carichiamo quei file su un server web. Puoi trovare alcuni buoni esempi per l'integrazione YUI + Ant in questo blog .

Ecco un esempio:

<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>

2
Frammento; simpatico. Esegui il retargeting delle script srcbuild su dev o copi semplicemente file non minimizzati nella directory / js compressa?
gustafc

Solo per la produzione, carica file compressi su quelli originali in public_html / js. La cosa buona è che non ci sono codifiche o cambi di percorso tra locale e produzione, la cosa brutta è che devi fare un po 'di caricamento e sovrascrittura manuale (sono sicuro che può essere automatizzato, ma per noi non ne vale la pena, caricare pochi file js una volta ogni tanto non è un grosso problema).
serg

Ho usato il tuo codice ma crea il file minimizzato alla radice del mio progetto, l'ho impostato <fileset dir="${generatedScriptsDir}" includes="**/*.js"/>ma non funziona. Come posso fare per generare il file nel ${generatedScriptsDir}?
Vadorequest

prova ad aggiungere l'attributo "dir" al tag "apply". assicurati che "$ {generatedScriptsDir}" sia stato creato come "proprietà" con la destinazione progettata
Rajasri.J

12

Penso che uno degli strumenti migliori e giusti per il lavoro sia wro4j Controlla https://github.com/wro4j/wro4j

Fa tutto ciò di cui hai bisogno:

  • Mantieni ben organizzate le risorse web del progetto (js e css)
  • Uniscili e minimizzali in fase di esecuzione (utilizzando un semplice filtro) o in fase di compilazione (utilizzando il plug-in Maven)
  • Gratuito e open source: rilasciato con una licenza Apache 2.0
  • diversi strumenti di minificazione supportati da wro4j: JsMin, compressore di chiusura di Google, YUI ecc
  • Facilissimo da usare. Supporta filtro servlet, Java semplice o configurazione Spring
  • Supporto Javascript e CSS Meta Frameworks: CoffeeScript, Less, Sass ecc
  • Convalida: JSLint, CSSLint ecc

Può essere eseguito in modalità di debug e di produzione. Basta specificare tutti i file che dovrebbe gestire / pre-elaborare e farà il resto.

Puoi semplicemente includere risorse unite, minimizzate e compresse in questo modo:

<script type="text/javascript" src="wro/all.js"></script>

2
Sembra davvero uno strumento ingegnoso. Grazie per l'aggiornamento!
gustafc

Aggiunge il controllo delle versioni ai file di risorse per forzare l'aggiornamento sul lato client? Non sono riuscito a trovare alcuna documentazione su questa funzione.
Qiang

L'unica cosa che mi manca davvero in wro4j è il prefisso css.
inafalcao

È possibile fornire contenuto statico (generato da wrosu App server) dal apacheserver web?
HybrisHelp

8

Ho scritto macro ant per il compilatore Google Closure e il compressore Yahoo e includo questo file in diversi progetti 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>
  • Integrazione: <import file="build-minifier.xml" />nel tuo build.xml, quindi invoca come al solito le attività ant:<gc-js dir="${build.js.dir}" src="prototype" /> <yc-js-all dir="${build.js.dir}" />

  • Scelta tra due minifiers: compilatore Google Closure e compressore Yahoo, dovresti scaricarli manualmente e posizionarli vicino al file xml

  • I minificatori saltano i file già compressi (che terminano con -min*)

  • Di solito creo tre versioni di script: non compresso (ad esempio prototype.js) per il debug, compresso con il compilatore di chiusura ( prototype-min-gc.js) per il server di produzione, compresso con Yahoo ( prototype-min-yc.js) per la risoluzione dei problemi perché il compilatore di chiusura utilizza ottimizzazioni rischiose e talvolta produce file compressi non validi e il compressore Yahoo è più sicuro

  • Il compressore Yahoo può minimizzare tutti i file in una directory con una singola macro, il compilatore Closure no


8

Ho provato due modi:

  1. utilizzando un filtro servlet. In modalità di produzione, il filtro viene attivato e comprime tutti i dati legati a URL come * .css o * .js
  2. utilizzando maven e yuicompressor-maven-plugin ; la compressione è eseguita una tantum, (durante il montaggio della guerra di produzione )

Ovviamente quest'ultima soluzione è migliore poiché non consuma risorse in fase di runtime (la mia webapp utilizza il motore dell'app Google) e non complica il codice dell'applicazione. Quindi ipotizza quest'ultimo caso nelle seguenti risposte:

Come si integra? Fa parte del tuo strumento di compilazione, di un filtro servlet, di un programma autonomo che esegue la post-elaborazione del file WAR o di qualcos'altro?

usando Maven

È facile da abilitare e disabilitare? Non è molto divertente provare a eseguire il debug di uno script minimizzato, ma è anche utile per uno sviluppatore essere in grado di verificare che la minificazione non interrompa nulla.

lo attivi solo durante il montaggio della guerra finale; in modalità sviluppo vedi la versione non compressa delle tue risorse

Funziona in modo trasparente o ha effetti collaterali (a parte quelli inerenti alla minificazione) che devo considerare nel mio lavoro quotidiano?

assolutamente

Quale minifier usa?

Compressore YUI

Manca qualche caratteristica a cui puoi pensare?

no, è molto completo e facile da usare

Cosa ti piace di questo?

è integrato con il mio strumento preferito (maven) e il plugin è nel repository centrale (un buon cittadino esperto)


Plugin Maven - carino. Peccato che i miei progetti attuali utilizzino tutti ant :)
gustafc

puoi creare un target che compila un "file war di produzione", utilizzando YUI ant task
dfa

4

Penso che tu abbia bisogno di una libreria di compressione, ad esempio il tag Granule.

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

Esegue gzip e combina javascript avvolti dal tag g: compress utilizzando metodi diversi, ha anche il task Ant

il codice di esempio è:

<G: impacco>
  <script type = "text / javascript" src = "common.js" />
  <script type = "text / javascript" src = "closing / goog / base.js" />
  <Script>
       goog.require ( 'goog.dom');
       goog.require ( 'goog.date');
       goog.require ( 'goog.ui.DatePicker');
  </ Script>
  <script type = "text / javascript">
      var dp = nuovo goog.ui.DatePicker ();
      dp.render (document.getElementById ( 'datepicker'));
  </ Script>
</ G: comprimere>
...


Sì, sembra piuttosto carino.
gustafc

3

Sono davvero sorpreso che nessuno abbia menzionato JAWR - https://jawr.github.io

È abbastanza maturo e supporta tutte le funzionalità standard previste e un po 'di più. Ecco come si oppone agli eccellenti criteri del PO.

Come si integra? Fa parte del tuo strumento di compilazione, di un filtro servlet, di un programma autonomo che esegue la post-elaborazione del file WAR o di qualcos'altro?

Inizialmente ha eseguito l'elaborazione / il sollevamento pesante all'avvio dell'applicazione e il servizio era basato su un servlet . A partire da 3.x hanno aggiunto il supporto per l' integrazione in fase di compilazione .

Il supporto per JSP e Facelets viene fornito tramite una libreria di tag JSP personalizzata per importare le risorse elaborate. In aggiunta a ciò, è implementato un caricatore di risorse JS che supporta il caricamento delle risorse da pagine HTML statiche .

È facile da abilitare e disabilitare? Non è molto divertente provare a eseguire il debug di uno script minimizzato, ma è anche utile per uno sviluppatore essere in grado di verificare che la minificazione non interrompa nulla.

È debug=ondisponibile un'opzione da utilizzare prima dell'avvio dell'applicazione e un GETparametro personalizzato può essere specificato su singole richieste in produzione per attivare o disattivare la modalità di debug in modo selettivo in fase di esecuzione per tale richiesta.

Quale minifier usa?

Per JS supporta YUI Compressor e JSMin, per CSS non ne sono sicuro.

Manca qualche caratteristica a cui puoi pensare?

SASSmi viene in mente il supporto. Detto questo, supporta LESS.


2

Il nostro progetto lo ha gestito in molti modi, ma abbiamo continuato a utilizzare YUI Compressor attraverso le nostre diverse iterazioni.

Inizialmente avevamo un servlet che gestiva la compressione per JavaScript la prima volta che si accedeva a quel particolare file; è stato quindi memorizzato nella cache. Avevamo già un sistema in atto per gestire i file delle proprietà personalizzate, quindi abbiamo semplicemente aggiornato i nostri file di configurazione per supportare l'abilitazione o la disabilitazione del compressore a seconda dell'ambiente in cui stavamo lavorando.

Ora gli ambienti di sviluppo non usano mai JavaScript compresso per scopi di debug. Invece gestiamo la compressione nel nostro processo di compilazione quando esportiamo la nostra applicazione in un file WAR.

Il nostro client non ha mai sollevato preoccupazioni sulla compressione e gli sviluppatori non se ne accorgono finché non decidono di eseguire il debug di JavaScript. Quindi direi che è piuttosto trasparente con effetti collaterali minimi, se non nessuno.


Come usi il compressore YUI dal tuo processo di compilazione? Il plugin Maven o qualcos'altro?
gustafc

1
Spiacenti, attualmente utilizziamo Ant. Ecco un link utile per Ant Task: blog.gomilko.com/2007/11/29/yui-compression-tool-as-ant-task
doomspork

1

Questo ha funzionato per me: 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>

Ho ricevuto $ {jar.yui.compressor} da search.maven.org: search.maven.org/…
Reverse Tarzan

1

Sto scrivendo un framework per la gestione delle risorse web, chiamato humpty . Mira ad essere più semplice e più moderno di jawr o wro4j utilizzando WebJars e ServiceLoaders.

Come si integra? Fa parte del tuo strumento di compilazione, di un filtro servlet, di un programma autonomo che esegue la post-elaborazione del file WAR o di qualcos'altro?

In fase di sviluppo, un servlet elabora le risorse secondo necessità. Gli asset verrebbero quindi precompilati prima della produzione e inseriti in una cartella pubblica, in modo che l'unica parte utilizzata generi gli include corretti nell'HTML.

È facile da abilitare e disabilitare? Non è molto divertente provare a eseguire il debug di uno script minimizzato, ma è anche utile per uno sviluppatore essere in grado di verificare che la minificazione non interrompa nulla.

Ciò sarebbe possibile passando dalla modalità di sviluppo a quella di produzione.

Funziona in modo trasparente o ha effetti collaterali (a parte quelli inerenti alla minificazione) che devo considerare nel mio lavoro quotidiano?

Credo che sia trasparente, ma favorisce fortemente l'uso di WebJars.

Quale minifier usa?

Qualunque sia quello utilizzato dal plugin che hai inserito nel tuo classpath. Attualmente sto cercando di scrivere un plug-in per il compilatore di chiusura di Google.

Manca qualche caratteristica a cui puoi pensare?

Ancora pre-rilascio, anche se lo sto usando in produzione. Il plugin Maven ha ancora bisogno di molto lavoro.

Cosa ti piace di questo?

La semplicità della semplice aggiunta di una dipendenza per configurare il framework

Cosa non ti piace di questo?

È il mio bambino, mi piace tutto;)


1

Davvero in ritardo per la festa qui, ma ho pensato che questo potrebbe aiutare qualcuno ancora alla ricerca di una risposta diversa:

Dopo aver provato a utilizzare YUI Compressor, sono rimasto deluso dal fatto che fosse incompatibile con le versioni più recenti di jQuery e Prism (le due principali librerie JS di terze parti di cui avevo bisogno per il mio progetto che volevo comprimere in un unico file). Quindi ho deciso di usare Terser , che è un fork di Uglify-JS che supporta ES6 +. Non sono stato in grado di farlo funzionare direttamente utilizzando l' <exec>attività, ma l'utilizzo del metodo della riga di comando di Windows funziona almeno per Win 10 (non dicendo che non possa funzionare altrimenti, ma questa è stata una soluzione molto semplice). Non è necessario aggiungere nient'altro alla variabile di sistema Path (poiché Node.JS viene solitamente aggiunto durante l'installazione). Per prima cosa utilizzo l' <concat>attività ANT per creare un file grande e non compresso. Usalo <fileset>perché preserverà l'ordine (se è importante, comunque).

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

Quindi utilizzare l' <exec>attività per eseguire qualsiasi programma NPM, come Terser. La pagina del manuale di Apache su questa attività indica che questa è la soluzione alternativa di Windows per eseguire file .bat, ma in realtà ti consente di eseguire praticamente qualsiasi applicazione a riga di comando (anche quelle che <exec>misteriosamente non riescono a trovare altrimenti).

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

Integrare? Fa parte di uno script di compilazione ANT (un plug-in DITA Open Toolkit per supportare JavaScript personalizzato, tra le altre cose, non un'applicazione Web Java, di per sé, ma utilizzando Java per creare output HTML5), quindi l'integrazione non era molto più che aggiungere quelli task su un nuovo target (c'è più codice relativo all'impostazione dei valori predefiniti e al controllo dei parametri di input!).

Facile da abilitare / disabilitare? Nel mio caso, ho un parametro che passo a ANT Build per includere la creazione e la minimizzazione del file JS. Quindi sì, esegue questo obiettivo solo se imposto il parametro su "Sì". È una cosa abbastanza facile da configurare in una build ANT.

Trasparente Finora, sembra non avere alcun effetto su nessuno dei numerosi file JS che includo. Alcuni di questi sono miei (e non sono un esperto di JS, in alcun modo) e alcuni sono, come ho detto, librerie JS comuni.

Minifier Terser, ma con questo metodo è possibile utilizzare praticamente qualsiasi minimizzato con input da riga di comando.

Mancano le caratteristiche? Terser funziona solo con JavaScript. Se voglio fare lo stesso per i miei file CSS (cosa che faccio), utilizzo YUI Compressor.

Like That è un progetto attualmente attivo e ha un buon supporto. Inoltre, l'attuale implementazione (chiamandola solo tramite il <exec>target ANT ) mi consente di sostituire i minifiers se dovessi aver bisogno di usare qualcos'altro lungo la strada.

Non mi piace che richiede Node.JS. Niente contro Node.JS, attenzione, solo che questo particolare progetto non ne ha bisogno altrimenti. Preferirei di gran lunga utilizzare un file Java .jar come YUI Compressor per questo (posso distribuirlo facilmente con un plug-in, se necessario).


Anche i ritardatari sono i benvenuti! Sono d'accordo che sia fastidioso che un progetto dipenda da due diversi ambienti di programmazione (Java + Node). Tuttavia, non sorprende che la maggior parte del lavoro Javascript avvenga nella comunità di Node, quindi non c'è molto da fare al riguardo e Terser sembra avere molto slancio in questi giorni. Grazie per il tuo contributo!
gustafc
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.