Wie automatisieren Sie die Javascript-Minimierung für Ihre Java-Webanwendungen?

122

Ich bin daran interessiert zu hören, wie Sie die Javascript-Minimierung für Ihre Java-Web-Apps bevorzugen. Hier sind einige Aspekte, die mich besonders interessieren:

  • Wie integriert es sich? Ist es Teil Ihres Build-Tools, eines Servlet-Filters, eines eigenständigen Programms, das die WAR-Datei nachbearbeitet, oder etwas anderes?
  • Ist es einfach zu aktivieren und zu deaktivieren ? Es ist sehr unlustig, ein minimiertes Skript zu debuggen, aber es ist auch nützlich, wenn ein Entwickler testen kann, ob die Minifizierung nichts kaputt macht.
  • Funktioniert es transparent oder hat es irgendwelche Nebenwirkungen (abgesehen von denen, die mit der Minimierung verbunden sind), die ich bei meiner täglichen Arbeit berücksichtigen muss?
  • Welchen Minifier benutzt es?
  • Fehlt es an Funktionen , an die Sie denken können?
  • Was magst du daran?
  • Was magst du nicht daran?

Dies wird hauptsächlich als Referenz für meine zukünftigen Projekte dienen (und hoffentlich finden es auch andere SOer informativ), sodass alle Arten von Tools interessant sind.

(Beachten Sie, dass dies keine Frage ist, welcher Minifier der beste ist . Wir haben bereits viele davon in der Nähe .)

gustafc
quelle
das sieht wirklich interessant aus, hatte noch nichts davon gehört. Alle Werkzeuge, die ich in einer Schnellsuche gefunden habe, sind manuelle Werkzeuge, die einmal ausgeführt werden. Es wäre schön, wenn es ein Plug-In für Ameise oder Maven gäbe. Hoffentlich hat jemand eine gute Antwort.
Jay
Und es scheint, dass jemand es getan hat - überprüfen Sie die Antwort von dfa: stackoverflow.com/questions/1379856/…
gustafc

Antworten:

65

Zusammenfassung

Wenn Sie in diesem Thread etwas Neues posten, bearbeiten Sie diesen Beitrag, um einen Link zu Ihrem zu erstellen.

gustafc
quelle
Minify-Maven und Maven Yui Kompressor spielten zum Zeitpunkt dieses Kommentars nicht gut mit ES6-Funktionen für mich
DPM
13

Wir verwenden die Ant-Task, um js-Dateien mit YUICompressor während der Erstellung der Produktion zu minimieren und das Ergebnis in einem separaten Ordner abzulegen. Dann laden wir diese Dateien auf einen Webserver hoch. In diesem Blog finden Sie einige gute Beispiele für die Integration von YUI + Ant .

Hier ist ein Beispiel:

<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
quelle
2
Snippet; nett. script srcRichten Sie Ihre On-Dev-Builds neu aus oder kopieren Sie einfach nicht minimierte Dateien in das komprimierte Verzeichnis / js?
Gustafc
Laden Sie nur für die Produktion komprimierte Dateien über Originaldateien in public_html / js hoch. Das Gute ist, dass es keine Codierung oder Pfadänderungen zwischen lokal und Produktion gibt. Das Schlechte ist, dass Sie einige manuelle Uploads und Überschreibungen durchführen müssen (ich bin sicher, dass dies automatisiert werden kann, aber für uns lohnt es sich nicht, es hochzuladen ab und zu ein paar js-dateien sind keine allzu große sache).
Serg
Ich habe Ihren Code verwendet, aber er erstellt die minimierte Datei im Stammverzeichnis meines Projekts. Ich habe sie festgelegt, <fileset dir="${generatedScriptsDir}" includes="**/*.js"/>aber sie funktioniert nicht. Wie kann ich die Datei in der generieren ${generatedScriptsDir}?
Vadorequest
Versuchen Sie, das Attribut 'dir' zum Tag 'apply' hinzuzufügen.
Stellen Sie
12

Ich denke, eines der besten und richtigen Tools für diesen Job ist wro4j. Schauen Sie sich https://github.com/wro4j/wro4j an

Es macht alles was Sie brauchen:

  • Halten Sie die Webressourcen des Projekts (js & css) gut organisiert
  • Führen Sie sie zur Laufzeit (mithilfe eines einfachen Filters) oder zur Erstellung (mithilfe des Maven-Plugins) zusammen und minimieren Sie sie.
  • Kostenlos und Open Source: Veröffentlicht unter einer Apache 2.0-Lizenz
  • Mehrere von wro4j unterstützte Minimierungstools: JsMin, Google Closure-Kompressor, YUI usw.
  • Sehr einfach zu bedienen. Unterstützt Servlet Filter-, Plain Java- oder Spring-Konfiguration
  • Unterstützung für Javascript- und CSS-Meta-Frameworks: CoffeeScript, Less, Sass usw.
  • Validierung: JSLint, CSSLint usw.

Kann sowohl im Debug- als auch im Produktionsmodus ausgeführt werden. Geben Sie einfach alle Dateien an, die verarbeitet / vorverarbeitet werden sollen, und der Rest wird erledigt.

Sie können einfach zusammengeführte, minimierte und komprimierte Ressourcen wie folgt einschließen:

<script type="text/javascript" src="wro/all.js"></script>
SZ Quadri
quelle
2
Scheint in der Tat wie ein geschicktes Werkzeug. Danke für das Update!
Gustafc
Fügt es Ressourcendateien eine Versionierung hinzu, um eine Aktualisierung auf der Clientseite zu erzwingen? Ich konnte keine Dokumentation zu dieser Funktion finden.
Qiang
Das einzige, was ich in wro4j wirklich vermisse, ist das CSS-Präfix.
Inafalcao
Ist es möglich, statische Inhalte (die wroauf dem App-Server generiert wurden ) vom apacheWebserver aus bereitzustellen?
HybrisHelp
8

Ich habe Ameisenmakros für den Google Closure-Compiler und den Yahoo-Kompressor geschrieben und diese Datei in verschiedene Webprojekte aufgenommen.

<?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>
  • Integration: <import file="build-minifier.xml" />Rufen Sie in Ihrer build.xml wie gewohnt Ant-Tasks auf:<gc-js dir="${build.js.dir}" src="prototype" /> <yc-js-all dir="${build.js.dir}" />

  • Sie können zwischen zwei Minifizierern wählen: dem Google Closure-Compiler und dem Yahoo-Kompressor. Sie sollten sie manuell herunterladen und in der Nähe der XML-Datei platzieren

  • Minifahrer überspringen bereits komprimierte Dateien (endend mit -min*)

  • Normalerweise mache ich drei Versionen des Skripts: unkomprimiert (z. B. prototype.js) zum Debuggen, komprimiert mit Closure Compiler ( prototype-min-gc.js) für Produktionsserver, komprimiert mit Yahoo ( prototype-min-yc.js) zur Fehlerbehebung, da Closure Compiler riskante Optimierungen verwendet und manchmal ungültige komprimierte Dateien erzeugt und Yahoo Compressor sicherer ist

  • Der Yahoo-Kompressor kann alle Dateien in einem Verzeichnis mit einem einzigen Makro minimieren, der Closure-Compiler nicht

Sieger
quelle
8

Ich habe zwei Möglichkeiten ausprobiert:

  1. mit einem Servlet-Filter. Im Produktionsmodus ist der Filter aktiviert und komprimiert alle an URLs gebundenen Daten wie * .css oder * .js
  2. mit Maven und Yuicompressor-Maven-Plugin ; Die Kompression wird unantantiert durchgeführt (bei der Zusammenstellung des Produktionskrieges ).

Natürlich ist die letztere Lösung besser, da sie zur Laufzeit keine Ressourcen verbraucht (meine Webanwendung verwendet die Google App Engine) und Ihren Anwendungscode nicht kompliziert. Nehmen Sie diesen letzteren Fall in den folgenden Antworten an:

Wie integriert es sich? Ist es Teil Ihres Build-Tools, eines Servlet-Filters, eines eigenständigen Programms, das die WAR-Datei nachbearbeitet, oder etwas anderes?

mit Maven

Ist es einfach zu aktivieren und zu deaktivieren? Es ist sehr unlustig, ein minimiertes Skript zu debuggen, aber es ist auch nützlich, wenn ein Entwickler testen kann, ob die Minifizierung nichts kaputt macht.

Sie aktivieren es nur, wenn Sie den letzten Krieg zusammenstellen. Im Entwicklungsmodus sehen Sie die unkomprimierte Version Ihrer Ressourcen

Funktioniert es transparent oder hat es irgendwelche Nebenwirkungen (abgesehen von denen, die mit der Minimierung verbunden sind), die ich bei meiner täglichen Arbeit berücksichtigen muss?

absolut

Welchen Minifier benutzt es?

YUI-Kompressor

Fehlt es an Funktionen, an die Sie denken können?

Nein, es ist sehr vollständig und einfach zu bedienen

Was magst du daran?

Es ist in mein Lieblings-Tool (Maven) integriert und das Plugin befindet sich im zentralen Repository (ein guter Maven-Bürger).

dfa
quelle
Maven Plugin - schön. Schade, dass meine aktuellen Projekte alle Ameisen verwenden :)
Gustafc
Sie können ein Ziel erstellen, das eine "Produktionskriegsdatei" erstellt, indem Sie die YUI-Ameisenaufgabe verwenden
dfa
4

Ich denke, Sie benötigen eine Komprimierungsbibliothek, zum Beispiel ein Granule-Tag.

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

Es gzip und kombiniert Javascripts, die von g: compress tag mit verschiedenen Methoden umbrochen wurden, und hat auch eine Ant-Aufgabe

Codebeispiel ist:

<g: komprimieren>
  <script type = "text / javascript" src = "common.js" />
  <script type = "text / javascript" src = "Schließung / goog / base.js" />
  <script>
       goog.require ('goog.dom');
       goog.require ('goog.date');
       goog.require ('goog.ui.DatePicker');
  </ script>
  <script type = "text / javascript">
      var dp = new goog.ui.DatePicker ();
      dp.render (document.getElementById ('datepicker'));
  </ script>
</ g: komprimieren>
...

Andy Bell
quelle
Ja, das sieht ziemlich gut aus.
Gustafc
3

Ich bin wirklich überrascht, dass niemand JAWR erwähnt hat - https://jawr.github.io

Es ist ziemlich ausgereift und unterstützt alle zu erwartenden Standardfunktionen und ein bisschen mehr. Hier ist, wie es gegen die hervorragenden Kriterien des OP gilt.

Wie integriert es sich? Ist es Teil Ihres Build-Tools, eines Servlet-Filters, eines eigenständigen Programms, das die WAR-Datei nachbearbeitet, oder etwas anderes?

Ursprünglich wurde die Verarbeitung / das schwere Heben beim Start der Anwendung durchgeführt, und das Serving basierte auf einem Servlet . Ab 3.x wurde Unterstützung für die Integration zur Erstellungszeit hinzugefügt .

Die Unterstützung für JSP und Facelets wird über eine benutzerdefinierte JSP-Tag-Bibliothek bereitgestellt, um verarbeitete Ressourcen zu importieren. Darüber hinaus ist ein JS-Ressourcenlader implementiert, der das Laden der Ressourcen von statischen HTML-Seiten unterstützt .

Ist es einfach zu aktivieren und zu deaktivieren? Es ist sehr unlustig, ein minimiertes Skript zu debuggen, aber es ist auch nützlich, wenn ein Entwickler testen kann, ob die Minifizierung nichts kaputt macht.

Vor dem debug=onStart der Anwendung GETkann eine Option verwendet werden. Bei einzelnen Anforderungen in der Produktion kann ein benutzerdefinierter Parameter angegeben werden, um den Debug-Modus zur Laufzeit für diese Anforderung selektiv umzuschalten.

Welchen Minifier benutzt es?

Für JS unterstützt es YUI Compressor und JSMin, für CSS bin ich mir nicht sicher.

Fehlt es an Funktionen, an die Sie denken können?

SASSUnterstützung kommt mir in den Sinn. Das heißt, es unterstützt LESS.

Amr Mostafa
quelle
2

Unser Projekt hat es auf verschiedene Arten gehandhabt, aber wir haben den YUI-Kompressor in unseren verschiedenen Iterationen weiterhin verwendet.

Beim ersten Zugriff auf eine bestimmte Datei hatte ein Servlet zunächst die Komprimierung für JavaScript. es wurde dann zwischengespeichert. Wir hatten bereits ein System für die Verarbeitung von benutzerdefinierten Eigenschaftendateien. Daher haben wir unsere Konfigurationsdateien einfach aktualisiert, um das Aktivieren oder Deaktivieren des Kompressors je nach Umgebung, in der wir arbeiten, zu unterstützen.

Jetzt verwenden die Entwicklungsumgebungen niemals komprimiertes JavaScript zum Debuggen. Stattdessen übernehmen wir die Komprimierung in unserem Erstellungsprozess, wenn wir unsere Anwendung in eine WAR-Datei exportieren.

Unser Client hat nie Bedenken hinsichtlich der Komprimierung geäußert, und die Entwickler bemerken dies erst, wenn sie sich entscheiden, JavaScript zu debuggen. Ich würde also sagen, es ist ziemlich transparent mit minimalen, wenn überhaupt, Nebenwirkungen.

Doomspork
quelle
Wie verwenden Sie den YUI-Kompressor aus Ihrem Erstellungsprozess? Das Maven Plugin oder was anderes?
Gustafc
1
Entschuldigung, wir verwenden derzeit Ant. Hier ist ein nützlicher Link für die Ameisenaufgabe: blog.gomilko.com/2007/11/29/yui-compression-tool-as-ant-task
doomspork
1

Das hat bei mir funktioniert: 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>
Reverse Tarzan
quelle
Ich habe den $ {jar.yui.compressor} von search.maven.org erhalten: search.maven.org/…
Reverse Tarzan
1

Ich schreibe ein Framework für die Verwaltung von Webressourcen , das als humpty bezeichnet wird . Mit WebJars und ServiceLoaders soll es einfacher und moderner als jawr oder wro4j sein.

Wie integriert es sich? Ist es Teil Ihres Build-Tools, eines Servlet-Filters, eines eigenständigen Programms, das die WAR-Datei nachbearbeitet, oder etwas anderes?

In der Entwicklung verarbeitet ein Servlet die Assets nach Bedarf. Die Assets werden dann vor der Produktion vorkompiliert und in einem öffentlichen Ordner abgelegt, sodass nur die richtigen Includes im HTML-Code generiert werden.

Ist es einfach zu aktivieren und zu deaktivieren? Es ist sehr unlustig, ein minimiertes Skript zu debuggen, aber es ist auch nützlich, wenn ein Entwickler testen kann, ob die Minifizierung nichts kaputt macht.

Dies würde durch Umschalten zwischen Entwicklungs- und Produktionsmodus geschehen.

Funktioniert es transparent oder hat es irgendwelche Nebenwirkungen (abgesehen von denen, die mit der Minimierung verbunden sind), die ich bei meiner täglichen Arbeit berücksichtigen muss?

Ich glaube, es ist transparent, befürwortet aber nachdrücklich die Verwendung von WebJars.

Welchen Minifier benutzt es?

Welches Plugin Sie auch in Ihren Klassenpfad einfügen. Derzeit wird ein Plugin für den Google Closure Compiler geschrieben.

Fehlt es an Funktionen, an die Sie denken können?

Noch Pre-Release, obwohl ich es in der Produktion verwende. Das Maven-Plugin benötigt noch viel Arbeit.

Was magst du daran?

Die Einfachheit, nur eine Abhängigkeit zum Konfigurieren des Frameworks hinzuzufügen

Was magst du nicht daran?

Es ist mein Baby, ich liebe alles;)

Mwanji Ezana
quelle
1

Wirklich spät zur Party hier, aber ich dachte, das könnte jemandem helfen, der noch nach einer anderen Antwort sucht:

Nachdem ich versucht hatte, YUI Compressor zu verwenden, war ich enttäuscht, dass es nicht mit neueren Versionen von jQuery und Prism kompatibel war (die beiden wichtigsten JS-Bibliotheken von Drittanbietern, die ich für mein Projekt benötigte und die ich in eine einzige Datei komprimieren wollte). Deshalb habe ich mich für Terser entschieden , eine Gabelung von Uglify-JS, die ES6 + unterstützt. Ich konnte es nicht direkt mit der <exec>Aufgabe ausführen , aber die Verwendung der Windows-Befehlszeilenmethode funktioniert zumindest für Win 10 (ohne zu sagen, dass es sonst nicht funktionieren kann, aber dies war eine sehr einfache Umgehung). Sie müssen der Systemvariablen Path nichts anderes hinzufügen (da Node.JS normalerweise während der Installation hinzugefügt wird). Ich benutze zuerst die ANT- <concat>Aufgabe, um eine große, unkomprimierte Datei zu erstellen. Verwenden <fileset>Sie diese Option, um die Reihenfolge beizubehalten (wenn dies trotzdem wichtig ist).

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

Verwenden Sie dann die <exec>Aufgabe, um ein beliebiges NPM-Programm wie Terser auszuführen. Auf der Apache-Handbuchseite zu dieser Aufgabe wurde angegeben, dass dies die Windows-Problemumgehung zum Ausführen von .bat-Dateien ist. Sie können jedoch nahezu jede Befehlszeilenanwendung ausführen (auch solche, die auf <exec>mysteriöse Weise nicht anders zu finden sind).

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

Integrieren? Es ist Teil eines ANT-Build-Skripts (ein DITA Open Toolkit-Plugin, das unter anderem benutzerdefiniertes JavaScript unterstützt - keine Java-Webanwendung an sich, sondern Java zum Erstellen von HTML5-Ausgaben). Die Integration war also nicht viel mehr als das Hinzufügen dieser Aufgaben an ein neues Ziel (es gibt mehr Code zum Festlegen von Standardeinstellungen und Überprüfen von Eingabeparametern!).

Einfach zu aktivieren / deaktivieren? In meinem Fall habe ich einen Parameter, den ich an den ANT-Build übergebe, um das Erstellen und Minimieren der JS-Datei einzuschließen. Ja, dieses Ziel wird nur ausgeführt, wenn ich den Parameter auf "Ja" setze. Das ist ziemlich einfach in einem ANT-Build einzurichten.

Transparent Bisher scheint es keine Auswirkungen auf eine der verschiedenen JS-Dateien zu haben, die ich einbinde. Einige davon sind meine eigenen (und ich bin keineswegs ein JS-Experte), andere sind, wie bereits erwähnt, gängige JS-Bibliotheken.

Minifier Terser, aber Sie können mit dieser Methode fast jeden mit Befehlszeileneingabe minimierten verwenden.

Fehlen Funktionen? Terser funktioniert nur mit JavaScript. Wenn ich dasselbe für meine CSS-Dateien tun möchte (was ich auch tue), verwende ich YUI Compressor.

Wie Das ist es gerade aktives Projekt und eine gute Unterstützung. Außerdem <exec>kann ich mit der aktuellen Implementierung (die nur über das ANT- Ziel aufgerufen wird) Minifizierer austauschen, falls ich später etwas anderes verwenden muss.

Mag nicht, dass es Node.JS erfordert. Nichts gegen Node.JS, wohlgemerkt, nur dass dieses spezielle Projekt es sonst nicht braucht. Ich würde es vorziehen, dafür eine Java-JAR-Datei wie YUI Compressor zu verwenden (ich kann diese bei Bedarf problemlos mit einem Plugin verteilen).

Jason Coleman
quelle
Auch Nachzügler sind willkommen! Ich bin damit einverstanden, dass es lästig ist, wenn ein Projekt von zwei verschiedenen Programmierumgebungen abhängt (Java + Node). Trotzdem ist es nicht überraschend, dass die meisten Javascript-Arbeiten in der Node-Community stattfinden. Es gibt also nicht viel zu tun, und Terser scheint heutzutage viel Schwung zu haben. Vielen Dank für Ihren Beitrag!
Gustafc