How do you automate Javascript minification for your Java web applications?

我很想知道你是如何为你的 Javaweb 应用程序自动化简化 Javascript 的。下面是我特别感兴趣的几个方面:

  • 它如何 整合?它是构建工具的一部分、 servlet 过滤器、后处理 WAR 文件的独立程序,还是其他什么?
  • 易于启用和禁用吗?尝试调试一个缩小的脚本是非常无趣的,但是对于开发人员来说,能够测试这个缩小的脚本不会破坏任何东西也是很有用的。
  • 它是否工作 显而易见,或者它有任何副作用(除了那些固有的缩小) ,我必须考虑在我的日常工作?
  • 它使用哪个缩写
  • 你能想到 没有任何特征吗?
  • 你喜欢它什么?
  • 你喜欢它什么?

这将主要作为我未来项目的参考(希望其他 SOer 也能从中获得信息) ,因此各种工具都很有趣。

(请注意,这不是一个关于哪个缩小器是最好的问题。我们已经有很多这样的。)

74218 次浏览

我试了两种方法:

  1. 使用 servlet 过滤器。在生产模式下,过滤器被激活,它压缩任何绑定到 URL 的数据,如 * 。Css 或 * 。JS
  2. 使用 Maven 和 YuicCompressor-maven-plugin; 压缩是在单调的情况下进行的(当组装 production war时)

当然,后一种解决方案更好,因为它不会在运行时消耗资源(我的网络应用程序使用的是谷歌应用程序引擎) ,而且它不会使您的应用程序代码复杂化。因此,在下面的回答中假设后一种情况:

它是如何整合的?它是构建工具的一部分、 servlet 过滤器、后处理 WAR 文件的独立程序,还是其他什么?

使用 Maven

启用和禁用是否容易?尝试调试一个缩小的脚本是非常无趣的,但是对于开发人员来说,能够测试这个缩小的脚本不会破坏任何东西也是很有用的。

只有在组装最终战争时才激活它; 在开发模式下,您可以看到资源的未压缩版本

它的工作是否透明,或者它有任何副作用(除了那些固有的缩小) ,我必须考虑在我的日常工作?

absolutely

它使用哪个缩小器?

YUI 压缩机

它是否缺乏任何你能想到的特征?

不,它是非常完整和易于使用

你喜欢它什么?

it is integrated with my favourite tool (maven) and the plugin is in the central repository (a good maven citizen)

我们的项目已经以多种方式处理了它,但是我们通过不同的迭代继续使用 YUI 压缩机

在第一次访问特定文件时,我们最初有一个 servlet 处理 JavaScript 的压缩; 然后缓存该文件。我们已经有了一个处理自定义属性文件的系统,所以我们只需更新配置文件,以支持根据我们工作的环境启用或禁用压缩器。

现在,开发环境从不使用压缩的 JavaScript 进行调试。相反,在将应用程序导出到 WAR 文件时,我们在构建过程中处理压缩。

我们的客户从来没有提出对压缩的担忧,开发人员在决定调试 JavaScript 之前也没有注意到这一点。所以我认为它是相当透明的,如果有副作用的话,也是最小的。

我们使用 Ant 任务在生产构建期间使用 YUICompressor 缩小 js 文件,并将 result 放入一个单独的文件夹中。然后我们把这些文件上传到网络服务器。

这里有一个例子:

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

我认为您需要一个压缩库,例如 Granule 标记。

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

它使用不同的方法 gzip 和组合由 g: compress 标记包装的 javascript,还有 Ant 任务

代码示例如下:

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


我已经写了蚂蚁宏为谷歌闭包编译器和雅虎压缩机,并包括在不同的网络项目这个文件。

<?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>
  • 集成: 在 build.xml 中调用 <import file="build-minifier.xml" />,然后像往常一样调用 ant 任务: <gc-js dir="${build.js.dir}" src="prototype" /> <yc-js-all dir="${build.js.dir}" />

  • 选择两个小型化: GoogleClosure 编译器和 Yahoo 压缩器,您应该手动下载它们并放置在 xml 文件附近

  • 缩减器跳过已经压缩的文件(以 -min*结束)

  • Usually I make three versions of script: uncompressed (e.g. prototype.js) for debugging, compressed with closure compiler (prototype-min-gc.js) for production server, compressed with Yahoo (prototype-min-yc.js) for troubleshooting because closure compiler uses risky optimizations and sometimes produces invalid compressed file and Yahoo compressor is more safe

  • Yahoo compressor can minify all files in a dir with single macro, Closure compiler cannot

我认为最好的和正确的工具之一是工作是 Wro4j检查出 https://github.com/wro4j/wro4j

它能满足你的一切需求:

  • 保持项目网络资源(js & css)组织良好
  • 在运行时(使用简单的过滤器)或构建时(使用 maven 插件)合并和缩小它们
  • Free and open source: Released under an Apache 2.0 license
  • Wro4j 支持的几个缩小工具: JsMin、 Google Closure 压缩器、 YUI 等
  • Very easy to use. Supports Servlet Filter, Plain Java or Spring Configuration
  • JavaScript 和 CSS 元框架支持: CoffeeScript,Less,Sass 等
  • 验证: JSLint、 CSSLint 等

可以在调试和生产模式下运行。只需指定它应该处理/预处理的所有文件,其余的就交给它了。

You can simply include merged, minified and compressed resource like this:

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

这招对我很管用: 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>

我很惊讶没人提到 JAWR-https://j-a-w-r.github.io

它非常成熟,支持所有预期的标准特性,甚至更多。以下是它如何与 OP 的优秀标准相对立的。

How does it integrate? Is it part of your build tool, a servlet 过滤器,后处理 WAR 文件的独立程序,或者 还有别的事吗?

它最初在应用程序启动时进行处理/繁重的工作,并基于 Servlet提供服务。从3.x 开始,他们增加了对 在构建时集成的支持。

通过定制的 JSP 标记库提供对 JSP 和 Faclets 的支持,以导入处理过的资源。除此之外,还实现了一个支持 从静态 HTML 页面加载资源的 JS 资源加载器。

启用和禁用是否容易? 尝试调试一个 缩小的脚本,但它也有助于开发人员能够 测试缩小不会破坏任何东西。

在应用程序启动之前可以使用 debug=on选项,并且可以在生产环境中的单个请求中指定自定义 GET参数,以便在运行时有选择地为所述请求切换调试模式。

它使用哪个缩小器?

对于 JS,它支持 YUI 压缩器和 JSMin,对于 CSS,我不确定。

它是否缺乏任何你能想到的特征?

我想到了 SASS的支持,也就是说,它确实支持 LESS

我正在编写一个管理网络资产的框架,称为 矮蛋。通过使用 WebJars 和 ServiceLoader,它的目标是比 jawr 或 wro4j 更简单、更现代。

它是如何整合的?它是构建工具的一部分、 servlet 过滤器、后处理 WAR 文件的独立程序,还是其他什么?

在开发中,servlet 根据需要处理资产。然后,这些资产将在生产之前进行预编译,并放置在一个公用文件夹中,以便使用的唯一部分是生成正确的 HTML 中包含的内容。

启用和禁用是否容易?尝试调试一个缩小的脚本是非常无趣的,但是对于开发人员来说,能够测试这个缩小的脚本不会破坏任何东西也是很有用的。

这将通过在开发模式和生产模式之间切换来实现。

它的工作是否透明,或者它有任何副作用(除了那些固有的缩小) ,我必须考虑在我的日常工作?

I believe it is transparent, but does strongly favour the use of WebJars.

它使用哪个缩小器?

您放在类路径上的插件使用的任何一个。目前正在为 Google Closure Compiler 编写一个插件。

它是否缺乏任何你能想到的特征?

仍然是预发布版,虽然我在生产中使用它。

你喜欢它什么?

简单地添加一个依赖项来配置框架

你不喜欢它什么?

这是我的宝贝,我爱这一切;)

虽然已经很晚了,但我想这也许能帮助那些还在寻找不同答案的人:

在尝试使用 YUI Compressor 之后,我感到失望的是,它与最新版本的 jQuery 和 Prism (我的项目需要的两个主要的第三方 JS 库,我想把它们压缩到一个文件中)不兼容。所以我决定使用 泰瑟,它是 Uglify-JS 的一个分支,支持 ES6 + 。我无法使用 <exec>任务直接运行它,但使用 Windows 命令行方法至少对 Win 10有效(并不是说它不能在其他情况下运行,但这是一个非常容易的解决方案)。不需要向 Path 系统变量添加任何其他内容(因为 Node.JS 通常是在安装过程中添加的)。我首先使用 ANT <concat>任务生成一个大的、未压缩的文件。使用 <fileset>,因为它将保持顺序(如果这很重要,无论如何)。

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

然后使用 <exec>任务运行任何 NPM 程序,比如 Terser。关于此任务的 Apache 手册页指出这是 Windows 运行的解决方案。Bat 文件,但它实际上允许您运行几乎任何命令行应用程序(即使是那些 <exec>神秘地找不到其他命令行应用程序)。

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

融合?这是 ANT 构建脚本的一部分(一个支持自定义 JavaScript 的 DITA Open Toolkit 插件,除此之外——不是 Java Web 应用本身,而是使用 Java 来构建 HTML5输出) ,所以集成不过是将这些任务添加到一个新目标(有更多关于设置默认值和检查输入参数的代码!).

易于启用/禁用?在我的示例中,我有一个传递给 ANT Build 的参数,以便包含构建和缩小 JS 文件。所以,是的,它只执行这个目标,如果我设置参数为’是’。在 ANT 构建中,这是一个非常容易设置的东西。

到目前为止,它似乎对我包含的几个 JS 文件中的任何一个都没有影响。其中一些是我自己的(无论如何,我不是 JS 专家) ,还有一些,正如我提到的,是常见的 JS 库。

Minifier Terser, but you could use just about any minified with command line input with this method.

缺少特征? Terser 只有使用 JavaScript。如果我想对 CSS 文件做同样的事情(我确实这样做了) ,我使用 YUI Compressor。

喜欢 它是一个当前活跃的项目并且有很好的支持。另外,当前的实现(只通过 ANT <exec>目标调用它)允许我在需要使用其他东西时更换缩小器。

不喜欢 它需要 Node.JS。不是针对 Node.JS,提醒你,只是这个特殊的项目不需要它。我更喜欢用 Java。诸如 YUI Compressor 之类的 jar 文件(如果需要的话,我可以用插件轻松地发布它)。