Como você automatiza a minificação de Javascript para seus aplicativos da Web Java?


122

Estou interessado em saber como você prefere automatizar a minificação de Javascript para seus aplicativos da Web Java. Aqui estão alguns aspectos nos quais estou particularmente interessado:

  • Como se integra? Faz parte da sua ferramenta de construção, um filtro de servlet, um programa independente pós-processamento do arquivo WAR ou outra coisa?
  • É fácil ativar e desativar ? É muito engraçado tentar depurar um script minificado, mas também é útil para um desenvolvedor poder testar se a minificação não quebra nada.
  • Funciona de forma transparente ou tem algum efeito colateral (além dos inerentes à minificação) que devo considerar no meu trabalho cotidiano?
  • Qual minifier ele usa?
  • Será que não têm todas as características que você pode pensar?
  • O que você gosta sobre isso?
  • Do que você não gosta?

Isso servirá principalmente como referência para meus projetos futuros (e, esperançosamente, outros SOs acharão informativo também), portanto todos os tipos de ferramentas são interessantes.

(Observe que essa não é uma pergunta sobre qual minifier é melhor . Já temos muitos deles por aí.)


isso parece realmente interessante, não tinha ouvido falar. Todas as ferramentas que encontrei em uma pesquisa rápida são ferramentas manuais executadas uma vez. Seria bom se houvesse um plug para formiga ou maven. Espero que alguém tenha uma boa resposta.
Jay em Jay

E parece que alguém o fez - verifique a resposta do dfa: stackoverflow.com/questions/1379856/…
gustafc 4/09/09

Respostas:


65

O compressor minify-maven e maven yui não funcionou bem com os recursos do ES6 para mim até o momento deste comentário
DPM

13

Estamos usando a tarefa Ant para minificar arquivos js com o YUICompressor durante a construção da produção e colocar o resultado em uma pasta separada. Em seguida, carregamos esses arquivos em um servidor web. Você pode encontrar alguns bons exemplos para a integração do YUI + Ant neste blog .

Aqui está um exemplo:

<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
Snippet; legais. Você redireciona suas script srccompilações on dev ou apenas copia arquivos não minificados para o diretório / js compactado?
gustafc 04/09/09

Apenas para produção, envie arquivos compactados sobre arquivos originais em public_html / js. O bom é que não há alterações de codificação ou caminho entre o local e a produção, o ruim é que você precisa fazer um upload e substituição manuais (tenho certeza de que pode ser automatizado, mas para nós não vale a pena fazer o upload) alguns arquivos js de vez em quando não é grande coisa).
serg

Eu usei seu código, mas ele cria o arquivo minificado na raiz do meu projeto, defino, <fileset dir="${generatedScriptsDir}" includes="**/*.js"/>mas ele não funciona. Como posso fazer para gerar o arquivo no ${generatedScriptsDir}?
Vadorequest 26/03

tente adicionar o atributo 'dir' à tag 'apply'. verifique se '$ {generateScriptsDir}' foi criado como uma 'propriedade' com o destino projetado
Rajasri

12

Acho que uma das melhores e melhores ferramentas para o trabalho é o wro4j Confira https://github.com/wro4j/wro4j

Faz tudo o que você precisa:

  • Mantenha os recursos da web do projeto (js e css) bem organizados
  • Mesclar e reduzi-los em tempo de execução (usando um filtro simples) ou em tempo de construção (usando o plugin maven)
  • Código aberto e gratuito: lançado sob uma licença Apache 2.0
  • várias ferramentas de minificação suportadas pelo wro4j: JsMin, compressor do Google Closure, YUI etc.
  • Muito fácil de usar. Suporta Filtro de Servlet, Java Simples ou Configuração Spring
  • Suporte a Javascript e CSS Meta Frameworks: CoffeeScript, Less, Sass etc
  • Validação: JSLint, CSSLint etc

Pode ser executado nos modos de depuração e produção. Apenas especifique todos os arquivos que ele deve manipular / pré-processar e faz o resto.

Você pode simplesmente incluir recursos mesclados, minificados e compactados como este:

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

2
Parece uma ferramenta bacana mesmo. Obrigado por atualizar!
Gustafc #

Ele adiciona versões aos arquivos de recursos para forçar a atualização no lado do cliente? Não encontrei nenhuma documentação sobre esse recurso.
Qiang

A única coisa que realmente sinto falta no wro4j é o prefixo css.
Inafalcao

É possível veicular conteúdo estático (gerado pelo wroservidor de aplicativos) no servidor da apacheWeb?
usar o seguinte código

8

Escrevi macros para o compilador Google Closure e o compressor Yahoo e incluí esse arquivo em diferentes projetos da 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>
  • Integração: <import file="build-minifier.xml" />em seu build.xml, invoque as tarefas ant comuns:<gc-js dir="${build.js.dir}" src="prototype" /> <yc-js-all dir="${build.js.dir}" />

  • Escolha de dois minifiers: compilador do Google Closure e compressor do Yahoo, você deve baixá-los manualmente e colocar perto do arquivo xml

  • Os minimizadores pulam arquivos já compactados (terminando com -min*)

  • Geralmente, faço três versões de script: descompactado (por exemplo prototype.js) para depuração, compactado com o compilador de fechamento ( prototype-min-gc.js) para servidor de produção, compactado com o Yahoo ( prototype-min-yc.js) para solução de problemas porque o compilador de fechamento usa otimizações de risco e às vezes produz arquivos compactados inválidos e o compressor do Yahoo é mais seguro

  • O compressor do Yahoo pode reduzir todos os arquivos em um diretório com uma única macro. O compilador de fechamento não pode


8

Eu tentei de duas maneiras:

  1. usando um filtro de servlet. Quando no modo de produção, o filtro é ativado e compacta todos os dados limitados ao URL como * .css ou * .js
  2. usando o maven e o yuicompressor-maven-plugin ; a compressão é realizada sem tântalo (na montagem da guerra de produção )

Obviamente, a última solução é melhor, pois não consome recursos em tempo de execução (meu webapp está usando o google app engine) e não complica o código do aplicativo. Portanto, assuma este último caso nas seguintes respostas:

Como se integra? Faz parte da sua ferramenta de construção, um filtro de servlet, um programa independente pós-processamento do arquivo WAR ou outra coisa?

usando maven

É fácil ativar e desativar? É muito engraçado tentar depurar um script minificado, mas também é útil para um desenvolvedor poder testar se a minificação não quebra nada.

você o ativa apenas ao montar a guerra final; no modo de desenvolvimento, você vê a versão não compactada de seus recursos

Funciona de forma transparente ou tem algum efeito colateral (além dos inerentes à minificação) que devo considerar no meu trabalho cotidiano?

absolutamente

Qual minifier ele usa?

Compressor YUI

Falta algum recurso que você possa pensar?

não, é muito completo e fácil de usar

O que você gosta sobre isso?

está integrado à minha ferramenta favorita (maven) e o plug-in está no repositório central (um bom cidadão maven)


Plugin Maven - legal. Pena que meus projetos atuais todo o uso de formigas :)
gustafc

você pode criar um alvo que construir um "arquivo de guerra produção", usando a tarefa YUI formiga
dfa

4

Eu acho que você precisa de uma biblioteca de compactação, por exemplo, tag Granule.

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

Gzip e combina javascripts envolvidos pelo g: compress tag usando métodos diferentes, também possui a tarefa Ant

amostra de código é:

<g: comprimir>
  <tipo de script = "text / javascript" src = "common.js" />
  <tipo de script = "text / javascript" src = "encerramento / goog / base.js" />
  <script>
       goog.require ('goog.dom');
       goog.require ('goog.date');
       goog.require ('goog.ui.DatePicker');
  </script>
  <tipo de script = "text / javascript">
      var dp = novo goog.ui.DatePicker ();
      dp.render (document.getElementById ('datepicker'));
  </script>
</ g: comprimir>
...


Sim, isso parece bem bacana.
Gustafc

3

Estou realmente surpreso que ninguém tenha mencionado JAWR - https://jawr.github.io

É bastante maduro e suporta todos os recursos padrão que são esperados, e um pouco mais. Aqui está como ele se compara aos excelentes critérios do OP.

Como se integra? Faz parte da sua ferramenta de construção, um filtro de servlet, um programa independente pós-processamento do arquivo WAR ou outra coisa?

Originalmente, o processamento / levantamento pesado na inicialização e veiculação do aplicativo era baseado em um servlet . A partir do 3.x, eles adicionaram suporte para integração no tempo de construção .

O suporte a JSP e Facelets é fornecido por meio de uma biblioteca de tags JSP customizada para importar recursos processados. Além disso, é implementado um carregador de recursos JS que suporta o carregamento de recursos de páginas HTML estáticas .

É fácil ativar e desativar? É muito engraçado tentar depurar um script minificado, mas também é útil para um desenvolvedor poder testar se a minificação não quebra nada.

Uma debug=onopção está disponível para uso antes da inicialização do aplicativo e um GETparâmetro personalizado pode ser especificado em solicitações individuais na produção para alternar o modo de depuração seletivamente em tempo de execução para a solicitação.

Qual minifier ele usa?

Para JS, ele suporta YUI Compressor e JSMin; para CSS, não tenho certeza.

Falta algum recurso que você possa pensar?

SASSsuporte vem à mente. Dito isto, ele suporta LESS.


2

Nosso projeto lidou com isso de várias maneiras, mas continuamos usando o Compressor YUI em nossas diferentes iterações.

Inicialmente, tivemos um servlet manipulando a compactação para JavaScript na primeira vez em que um arquivo específico foi acessado; foi então armazenado em cache. Já tínhamos um sistema instalado para lidar com arquivos de propriedades personalizadas, portanto, simplesmente atualizamos nossos arquivos de configuração para permitir a ativação ou desativação do compressor, dependendo do ambiente em que estávamos trabalhando.

Agora, os ambientes de desenvolvimento nunca usam JavaScript compactado para fins de depuração. Em vez disso, lidamos com a compactação em nosso processo de compilação ao exportar nosso aplicativo para um arquivo WAR.

Nosso cliente nunca levantou preocupações sobre a compactação e os desenvolvedores não notam até decidirem depurar o JavaScript. Então, eu diria que é bastante transparente com o mínimo, se houver, de efeitos colaterais.


Como você usa o compressor YUI do seu processo de construção? O plugin Maven ou algo mais?
gustafc 04/09/09

1
Desculpe, nós usamos Ant atualmente. Aqui está um link útil para o Ant Task: blog.gomilko.com/2007/11/29/yui-compression-tool-as-ant-task
doomspork

1

Isso funcionou para mim: https://bitbucket.org/m6_russell_francis/yui-compressor-ant-task/wiki/

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

Eu tenho a $ {jar.yui.compressor} de search.maven.org: search.maven.org/...
reverso Tarzan

1

Estou escrevendo uma estrutura para gerenciar ativos da web, chamada humpty . Ele pretende ser mais simples e mais moderno que o jawr ou o wro4j usando WebJars e ServiceLoaders.

Como se integra? Faz parte da sua ferramenta de construção, um filtro de servlet, um programa independente pós-processamento do arquivo WAR ou outra coisa?

No desenvolvimento, um servlet processa os ativos conforme necessário. Os ativos seriam pré-compilados antes da produção e colocados em uma pasta pública, para que a única parte usada fosse gerar as inclusões corretas no HTML.

É fácil ativar e desativar? É muito engraçado tentar depurar um script minificado, mas também é útil para um desenvolvedor poder testar se a minificação não quebra nada.

Isso seria feito alternando entre os modos de desenvolvimento e produção.

Funciona de forma transparente ou tem algum efeito colateral (além dos inerentes à minificação) que devo considerar no meu trabalho cotidiano?

Eu acredito que é transparente, mas favorece fortemente o uso de WebJars.

Qual minifier ele usa?

Qualquer que seja o plug-in que você coloca no seu caminho de classe. Atualmente, está escrevendo um plug-in para o Google Closure Compiler.

Falta algum recurso que você possa pensar?

Ainda pré-lançamento, embora eu esteja usando na produção. O plugin maven ainda precisa de muito trabalho.

O que você gosta sobre isso?

A simplicidade de apenas adicionar uma dependência para configurar a estrutura

O que você não gosta nisso?

É meu bebê, eu amo tudo;)


1

Muito atrasado para a festa aqui, mas achei que isso poderia ajudar alguém ainda procurando uma resposta diferente:

Depois de tentar usar o YUI Compressor, fiquei desapontado por ser incompatível com versões mais recentes do jQuery e Prism (as duas principais bibliotecas JS de terceiros necessárias para o meu projeto, que eu queria compactar em um único arquivo). Decidi usar o Terser , que é um fork do Uglify-JS que suporta o ES6 +. Não consegui executá-lo diretamente usando a <exec>tarefa, mas usar o método de linha de comando do Windows funciona pelo menos para o Windows 10 (sem dizer que não pode funcionar de outra maneira, mas essa foi uma solução muito fácil). Não há necessidade de adicionar mais nada à variável de sistema Path (como o Node.JS geralmente é adicionado durante a instalação). Primeiro uso a <concat>tarefa ANT para criar um arquivo grande e não compactado. Use <fileset>como preservará a ordem (se isso for importante, de qualquer maneira).

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

Em seguida, use a <exec>tarefa para executar qualquer programa NPM, como o Terser. A página de manual do Apache nesta tarefa indicou que esta é a solução alternativa do Windows para a execução de arquivos .bat, mas realmente permite que você execute praticamente qualquer aplicativo de linha de comando (mesmo aqueles que <exec>misteriosamente não podem encontrar de outra maneira).

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

Integrar? Faz parte de um script de construção ANT (um plug-in DITA Open Toolkit para suportar JavaScript personalizado, entre outras coisas - não um aplicativo Java Web, por si só, mas usando Java para criar saída HTML5), portanto, a integração não foi muito mais do que adicionar aqueles tarefas para um novo destino (há mais código relacionado à configuração de padrões e à verificação de parâmetros de entrada!).

Fácil de ativar / desativar? No meu caso, tenho um parâmetro que passo para o ANT Build para incluir a construção e a minificação do arquivo JS. Então, sim, ele só executa esse destino se eu definir o parâmetro como 'Sim'. Isso é algo muito fácil de configurar em uma compilação do ANT.

Transparente Até agora, parece não ter efeito em nenhum dos vários arquivos JS que estou incluindo. Alguns deles são meus (e não sou especialista em JS, por qualquer meio) e alguns são, como mencionei, bibliotecas JS comuns.

Minifier Terser, mas você pode usar praticamente qualquer minificado com entrada de linha de comando com esse método.

Falta recursos? O Terser funciona apenas com JavaScript. Se eu quiser fazer o mesmo com meus arquivos CSS (o que eu faço), uso o Compressor YUI.

O Like That é um projeto atualmente ativo e tem um bom suporte. Além disso, a implementação atual (apenas chamando-a através do <exec>alvo ANT ) permite que eu troque os minificadores, caso eu precise usar outra coisa no caminho.

Não gosto disso, requer Node.JS. Nada contra o Node.JS, lembre-se, apenas que esse projeto em particular não precisa dele de outra forma. Eu preferiria usar um arquivo Java .jar como o YUI Compressor para isso (posso distribuir isso facilmente com um plugin, se necessário).


Os retardatários também são bem-vindos! Concordo que é incômodo ter um projeto dependente de dois ambientes de programação diferentes (Java + Node). Ainda assim, não surpreende que a maioria dos trabalhos sobre Javascript ocorra na comunidade Node, portanto não há muito o que fazer sobre isso, e Terser parece ter muito impulso atualmente. Obrigado pela sua contribuição!
Gustafc #
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.