¿Cómo automatizas la minificación de Javascript para tus aplicaciones web Java?


122

Me interesa saber cómo prefiere automatizar la minificación de Javascript para sus aplicaciones web Java. Aquí hay algunos aspectos en los que estoy particularmente interesado:

  • ¿Cómo se integra? ¿Es parte de su herramienta de compilación, un filtro de servlet, un programa independiente que procesa el archivo WAR u otra cosa?
  • ¿Es fácil habilitar y deshabilitar ? Es muy divertido intentar depurar un script minificado, pero también es útil para un desarrollador poder probar que la minificación no rompe nada.
  • ¿Funciona de manera transparente o tiene algún efecto secundario (aparte de los inherentes a la minificación) que debo tener en cuenta en mi trabajo diario?
  • ¿Qué minificador usa?
  • ¿ Le falta alguna característica que se le ocurra?
  • ¿Qué te gusta de ello?
  • ¿ Qué no te gusta de eso?

Esto servirá principalmente como referencia para mis proyectos futuros (y espero que otros SOers también lo encuentren informativo), por lo que todo tipo de herramientas son interesantes.

(Tenga en cuenta que esta no es una pregunta sobre qué minificador es el mejor . Ya tenemos muchos de ellos).


Esto parece realmente interesante, no había oído hablar de eso. Todas las herramientas que he encontrado en una búsqueda rápida son herramientas manuales que se ejecutan una vez. Sería bueno si hubiera un enchufe para hormiga o experto. Esperemos que alguien tenga una buena respuesta.
Jay

Y parece que alguien lo hizo - verifique la respuesta de dfa: stackoverflow.com/questions/1379856/…
gustafc

Respuestas:


65

13

Estamos utilizando la tarea Ant para minimizar archivos js con YUICompressor durante la compilación de producción y colocar el resultado en una carpeta separada. Luego cargamos esos archivos a un servidor web. Puede encontrar algunos buenos ejemplos para la integración de YUI + Ant en este blog .

Aquí hay un ejemplo:

<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
Retazo; bonito. ¿Reorganiza sus script srccompilaciones de desarrollo o simplemente copia archivos no minificados en el directorio comprimido / js?
gustafc

Solo para producción, cargue archivos comprimidos sobre los originales en public_html / js. Lo bueno es que no hay cambios de codificación o ruta entre lo local y la producción, lo malo es que tienes que hacer una carga y sobrescritura manual (estoy seguro de que puede automatizarse, pero para nosotros no vale la pena, cargar algunos archivos js de vez en cuando no es un gran problema).
serg

Utilicé su código pero crea el archivo minificado en la raíz de mi proyecto, lo configuré <fileset dir="${generatedScriptsDir}" includes="**/*.js"/>pero no funciona. ¿Cómo puedo hacer para generar el archivo en el ${generatedScriptsDir}?
Vadorequest

intente agregar el atributo 'dir' a la etiqueta 'apply'. asegúrese de que '$ {generateScriptsDir}' se haya creado como una 'propiedad' con el destino diseñado
Rajasri.J

12

Creo que una de las mejores y más adecuadas herramientas para el trabajo es wro4j Echa un vistazo a https://github.com/wro4j/wro4j

Hace todo lo que necesitas:

  • Mantenga los recursos web del proyecto (js y css) bien organizados
  • Fusionarlos y minimizarlos en tiempo de ejecución (usando un filtro simple) o en tiempo de compilación (usando el complemento Maven)
  • Gratis y de código abierto: lanzado bajo una licencia Apache 2.0
  • Varias herramientas de minificación compatibles con wro4j: JsMin, compresor Google Closure, YUI, etc.
  • Muy facil de usar. Admite configuración de filtro de servlet, Java sin formato o Spring
  • Soporte de Javascript y CSS Meta Frameworks: CoffeeScript, Less, Sass, etc.
  • Validación: JSLint, CSSLint, etc.

Puede ejecutarse tanto en modo de depuración como de producción. Simplemente especifique todos los archivos que debe manejar / preprocesar y hace el resto.

Simplemente puede incluir recursos combinados, minificados y comprimidos como este:

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

2
Parece una herramienta ingeniosa de hecho. Gracias por actualizar!
gustafc 01 de

¿Agrega versiones a los archivos de recursos para forzar la actualización en el lado del cliente? No pude encontrar ninguna documentación sobre esta característica.
Qiang

Lo único que realmente extraño en wro4j es el prefijo css.
Inafalcao

¿Es posible servir contenido estático (generado por wroel servidor de aplicaciones) desde apacheel servidor web?
HybrisHelp

8

He escrito macros de hormigas para el compilador Google Closure y el compresor Yahoo e incluyo este archivo en diferentes proyectos 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>
  • Integración: <import file="build-minifier.xml" />en su build.xml, luego invoque como de costumbre las tareas ant:<gc-js dir="${build.js.dir}" src="prototype" /> <yc-js-all dir="${build.js.dir}" />

  • Elección de dos minificadores: compilador Google Closure y compresor Yahoo, debe descargarlos manualmente y colocarlos cerca del archivo xml

  • Los minificadores omiten archivos ya comprimidos (que terminan en -min*)

  • Por lo general, hago tres versiones del script: sin comprimir (por ejemplo prototype.js) para depurar, comprimido con el compilador de cierre ( prototype-min-gc.js) para el servidor de producción, comprimido con Yahoo ( prototype-min-yc.js) para la resolución de problemas porque el compilador de cierre utiliza optimizaciones arriesgadas y a veces produce un archivo comprimido no válido y el compresor de Yahoo es más seguro

  • El compresor de Yahoo puede minimizar todos los archivos en un directorio con una sola macro, el compilador de cierre no puede


8

Lo intenté de dos maneras:

  1. utilizando un filtro de servlet. Cuando está en modo de producción, el filtro se activa y comprime cualquier dato enlazado a URL como * .css o * .js
  2. usando maven y yuicompressor-maven-plugin ; la compresión se realiza una-tantum (al armar la guerra de producción )

Por supuesto, la última solución es mejor ya que no consume recursos en tiempo de ejecución (mi aplicación web está usando el motor de aplicaciones de Google) y no complica el código de su aplicación. Asuma este último caso en las siguientes respuestas:

¿Cómo se integra? ¿Es parte de su herramienta de compilación, un filtro de servlet, un programa independiente que procesa el archivo WAR u otra cosa?

usando maven

¿Es fácil habilitar y deshabilitar? Es muy divertido intentar depurar un script minificado, pero también es útil para un desarrollador poder probar que la minificación no rompe nada.

solo lo activas al armar la guerra final; en el modo de desarrollo, verá la versión sin comprimir de sus recursos

¿Funciona de manera transparente o tiene algún efecto secundario (aparte de los inherentes a la minificación) que debo tener en cuenta en mi trabajo diario?

absolutamente

¿Qué minificador usa?

Compresor YUI

¿Le falta alguna característica que se le ocurra?

no, es muy completo y fácil de usar

¿Qué te gusta de ello?

está integrado con mi herramienta favorita (maven) y el complemento está en el repositorio central (un buen ciudadano maven)


Complemento Maven: agradable. Lástima que todos mis proyectos actuales usen hormiga :)
gustafc

puede crear un objetivo que construir un "archivo de la guerra la producción", utilizando la tarea de hormiga YUI
DFA

4

Creo que necesita una biblioteca de compresión, por ejemplo, la etiqueta Granule.

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

Gzip y combina javascripts envueltos por g: comprimir etiqueta usando diferentes métodos, también tiene la tarea Ant también

muestra de código es:

<g: comprimir>
  <script type = "text / javascript" src = "common.js" />
  <script type = "text / javascript" src = "cierre / 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: comprimir>
...


Sí, eso se ve bastante ingenioso.
gustafc

3

Estoy realmente sorprendido de que nadie haya mencionado JAWR - https://jawr.github.io

Es bastante maduro y admite todas las características estándar que se esperan, y un poco más. Así es como se sostiene contra los excelentes criterios del OP.

¿Cómo se integra? ¿Es parte de su herramienta de compilación, un filtro de servlet, un programa independiente que procesa el archivo WAR u otra cosa?

Originalmente realizó el procesamiento / trabajo pesado al inicio de la aplicación y el servicio se basó en un servlet . A partir de 3.x, agregaron soporte para la integración en el momento de la compilación .

El soporte para JSP y Facelets se proporciona a través de una biblioteca de etiquetas JSP personalizada para importar recursos procesados. Además de eso, se implementa un cargador de recursos JS que admite cargar los recursos desde páginas HTML estáticas .

¿Es fácil habilitar y deshabilitar? Es muy divertido intentar depurar un script minificado, pero también es útil para un desarrollador poder probar que la minificación no rompe nada.

Hay una debug=onopción disponible para usar antes del inicio de la aplicación, y GETse puede especificar un parámetro personalizado en solicitudes individuales en producción para alternar el modo de depuración selectivamente en tiempo de ejecución para dicha solicitud.

¿Qué minificador usa?

Para JS es compatible con YUI Compressor y JSMin, para CSS no estoy seguro.

¿Le falta alguna característica que se le ocurra?

SASSEl apoyo viene a la mente. Dicho esto, sí es compatible LESS.


2

Nuestro proyecto lo ha manejado de varias maneras, pero hemos seguido usando el Compresor YUI a través de nuestras diferentes iteraciones.

Inicialmente, un servlet manejó la compresión de JavaScript la primera vez que se accedió a ese archivo en particular; luego fue almacenado en caché. Ya teníamos un sistema para manejar archivos de propiedades personalizadas, por lo que simplemente actualizamos nuestros archivos de configuración para permitir habilitar o deshabilitar el compresor según el entorno en el que estuviéramos trabajando.

Ahora los entornos de desarrollo nunca usan JavaScript comprimido para propósitos de depuración. En su lugar, manejamos la compresión en nuestro proceso de compilación al exportar nuestra aplicación a un archivo WAR.

Nuestro cliente nunca ha expresado su preocupación por la compresión y los desarrolladores no lo notan hasta que deciden depurar JavaScript. Entonces, diría que es bastante transparente con efectos secundarios mínimos, si los hay.


¿Cómo utiliza el compresor YUI de su proceso de compilación? ¿El complemento Maven o algo más?
gustafc

1
Lo sentimos, usamos Ant actualmente. Aquí hay un enlace útil para la tarea Ant: blog.gomilko.com/2007/11/29/yui-compression-tool-as-ant-task
doomspork

1

Esto funcionó para mí: 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>

Obtuve el $ {jar.yui.compressor} de search.maven.org: search.maven.org/…
Reverse Tarzan el

1

Estoy escribiendo un marco para administrar activos web, llamado humpty . Su objetivo es ser más simple y más moderno que jawr o wro4j mediante WebJars y ServiceLoaders.

¿Cómo se integra? ¿Es parte de su herramienta de compilación, un filtro de servlet, un programa independiente que procesa el archivo WAR u otra cosa?

En desarrollo, un servlet procesa los activos según sea necesario. Luego, los activos se precompilarán antes de la producción y se colocarán en una carpeta pública, de modo que la única parte que se use es generar las inclusiones correctas en el HTML.

¿Es fácil habilitar y deshabilitar? Es muy divertido intentar depurar un script minificado, pero también es útil para un desarrollador poder probar que la minificación no rompe nada.

Eso se haría cambiando entre los modos de desarrollo y producción.

¿Funciona de manera transparente o tiene algún efecto secundario (aparte de los inherentes a la minificación) que debo tener en cuenta en mi trabajo diario?

Creo que es transparente, pero favorece fuertemente el uso de WebJars.

¿Qué minificador usa?

Cualquiera que sea el complemento que pongas en tu classpath. Actualmente estoy buscando escribir un complemento para el compilador de cierre de Google.

¿Le falta alguna característica que se le ocurra?

Todavía prelanzamiento, aunque lo estoy usando en producción. El complemento Maven todavía necesita mucho trabajo.

¿Qué te gusta de ello?

La simplicidad de simplemente agregar una dependencia para configurar el marco

¿Qué no te gusta de eso?

Es mi bebé, lo amo todo;)


1

Realmente tarde para la fiesta aquí, pero pensé que esto podría ayudar a alguien que todavía busca una respuesta diferente:

Después de tratar de usar YUI Compressor, me decepcionó que fuera incompatible con las versiones más recientes de jQuery y Prism (las dos bibliotecas principales de JS de terceros que necesitaba para mi proyecto que quería comprimir en un solo archivo). Así que decidí usar Terser , que es una bifurcación de Uglify-JS que admite ES6 +. No pude hacer que se ejecute directamente usando la <exec>tarea, pero usar el método de línea de comandos de Windows funciona para Win 10, al menos (no digo que no pueda funcionar de otra manera, pero esta fue una solución muy fácil). No es necesario agregar nada más a la variable del sistema Path (ya que Node.JS generalmente se agrega durante la instalación). Primero uso la <concat>tarea ANT para hacer un archivo grande y sin comprimir. Úselo <fileset>ya que preservará el orden (si eso es importante, de todos modos).

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

Luego use la <exec>tarea para ejecutar cualquier programa NPM, como Terser. La página del manual de Apache sobre esta tarea indica que esta es la solución alternativa de Windows para ejecutar archivos .bat, pero realmente le permite ejecutar casi cualquier aplicación de línea de comandos (incluso aquellas que <exec>misteriosamente no pueden encontrar de otra manera).

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

¿Integrar? Es parte de un script de compilación ANT (un complemento de DITA Open Toolkit para admitir JavaScript personalizado, entre otras cosas, no una aplicación web Java, per se, sino que usa Java para construir una salida HTML5), por lo que la integración no fue mucho más que agregar esos tareas a un nuevo objetivo (¡hay más código con respecto a la configuración de valores predeterminados y la verificación de los parámetros de entrada!

Fácil de habilitar / deshabilitar? En mi caso, tengo un parámetro que paso a ANT Build para incluir la construcción y la minificación del archivo JS. Entonces, sí, solo realiza este objetivo si configuro el parámetro en 'Sí'. Eso es algo bastante fácil de configurar en una compilación ANT.

Transparente Hasta ahora, parece no tener efecto en ninguno de los varios archivos JS que estoy incluyendo. Algunos de ellos son míos (y no soy un experto en JS, de ninguna manera) y algunos son, como mencioné, bibliotecas JS comunes.

Minifier Terser, pero podría usar casi cualquier minified con entrada de línea de comando con este método.

¿Carece de características? Terser solo funciona con JavaScript. Si quiero hacer lo mismo con mis archivos CSS (que hago), uso YUI Compressor.

Like That es un proyecto actualmente activo y tiene un buen apoyo. Además, la implementación actual (solo llamándolo a través del <exec>objetivo ANT ) me permite cambiar los minificadores si necesito usar algo más en el futuro.

No me gusta que requiere Node.JS. Nada en contra de Node.JS, ten en cuenta, solo que este proyecto en particular no lo necesita de otra manera. Preferiría usar un archivo Java .jar como YUI Compressor para esto (puedo distribuirlo fácilmente con un complemento si lo necesito).


¡Los recién llegados también son bienvenidos! Estoy de acuerdo en que es molesto que un proyecto dependa de dos entornos de programación diferentes (Java + Node). Aún así, no es sorprendente que la mayoría del trabajo de Javascript ocurra en la comunidad Node, por lo que no hay mucho que hacer al respecto, y Terser parece tener un gran impulso en estos días. Gracias por tu aporte!
gustafc
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.