問題描述
我有一個使用 Maven 構建的 Web 項目,我正在嘗試找出使用 RequireJS 編譯器編譯 JavaScript 文件的最佳方法(這個問題也適用于任何編譯器/壓縮器).
I have a web project that's built with Maven and I'm trying to figure out the best way to compile the JavaScript files with the RequireJS compiler (this question could apply to any compiler/minifier as well).
我有一個可行的設置,但需要改進:
I have a setup that works, but it needs improvement:
我已經打包了第 3 方 JavaScript 庫,它們作為依賴項被下載,然后與 WAR Overlay 插件一起添加.
I've packaged the 3rd party JavaScript libraries and they are being downloaded as dependencies and then added with the WAR Overlay plugin.
我有一個 Exec 插件任務,它在目標目錄中運行 RequireJS 編譯器.我目前在包目標運行后手動運行 exec:exec
(因此 WAR 內容放置在目標目錄中).
I have an Exec plugin task that runs the RequireJS compiler inside the target directory. I currently manually run exec:exec
after the package target runs (and therefore the WAR contents are placed in the target directory).
我想要的是讓 JS 編譯成為主要 (Java) 編譯的一部分.JS 編譯器本身(需要 JS)在編譯后發生的 WAR 覆蓋階段作為依賴項下載.因此,我需要下載和解壓縮 Require JS 文件,并且需要在 Java 編譯之前/期間/之后使用這些文件運行 JS 編譯.
What I would like instead is to make JS compilation part of main (Java) compilation. The JS compiler itself (Require JS) is downloaded as a dependency during the WAR overlay phase which happens after compilation. So, I need the Require JS files to be downloaded and unpacked and I need to run the JS compilation using those files, before/during/after Java compilation.
我確信有幾種方法可以實現這一目標.我正在尋找最優雅的解決方案.
I'm sure there could be several ways to achieve this. I'm looking for the most elegant solution.
更新:現有的 POM 片段
我已經壓縮并添加到我們的存儲庫管理器中的 JavaScript 依賴項:
I have JavaScript dependencies which I have zipped and added to our repository manager:
<dependency>
<groupId>org.requirejs</groupId>
<artifactId>requirejs</artifactId>
<version>0.22.0</version>
<classifier>repackaged</classifier>
<type>zip</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.jqueryui</groupId>
<artifactId>jquery-ui</artifactId>
<version>1.8.7</version>
<classifier>repackaged</classifier>
<type>zip</type>
<scope>runtime</scope>
</dependency>
請注意,RequireJS 本身(編譯其余庫所必需的)也作為外部依賴項加載.所以第一件事是,我需要先下載并解壓縮此依賴項,然后才能開始 RequireJS 編譯.
Take note that RequireJS itself (which is required for the compilation of the rest of libraries) is also loaded as an external dependency. So the first thing is, I need this dependency to be downloaded and unzipped before I can commence with RequireJS compilation.
這些依賴項正在使用 WAR Overlay 插件添加到 WAR:
These dependencies are being added to the WAR using the WAR Overlay plugin:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<overlays>
<overlay>
<groupId>org.requirejs</groupId>
<artifactId>requirejs</artifactId>
<classifier>repackaged</classifier>
<type>zip</type>
<targetPath>lib</targetPath>
<includes>
<include>requirejs/require.js</include>
<include>requirejs/require/*</include>
<include>requirejs/build/**</include>
</includes>
</overlay>
<overlay>
<groupId>com.jqueryui</groupId>
<artifactId>jquery-ui</artifactId>
<classifier>repackaged</classifier>
<type>zip</type>
<targetPath>lib</targetPath>
</overlay>
</overlays>
</configuration>
</plugin>
即使我不需要 requirejs/build/**
最終進入 WAR,我還是將其作為覆蓋的一部分包含在內以獲取解壓縮的 RequireJS 構建腳本,僅僅是因為我還沒有找到更好的方法.
Even though I don't need requirejs/build/**
to end up in the WAR, I'm including it as part of the overlay to get the unzipped RequireJS build scripts, simply because I haven't figured out a better way.
然后我有一個執行編譯的 Exec 插件任務.但請注意,此任務尚未添加到正常的編譯工作流程中:我必須在 WAR 打包完成后使用 mvn exec:exec
手動調用它:
Then I have a Exec plugin task that performs the compilation. But note that this task hasn't been added to the normal compilation work flow: I have to manually invoke it with mvn exec:exec
after the WAR packaging is done:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>lib/requirejs/build/build.bat</executable>
<workingDirectory>${project.build.directory}/${project.artifactId}</workingDirectory>
<arguments>
<argument>name=bootstrap</argument>
<argument>out=combined.js</argument>
<argument>baseUrl=scripts</argument>
<argument>optimize=closure</argument>
<argument>excludeShallow=plugins/manifest</argument>
</arguments>
</configuration>
</plugin>
所以,有些問題是:
- 如何為編譯和 WAR 打包步驟提取單個壓縮依賴項的不同部分?還是我必須創建兩個 zip 文件,一個僅包含運行時內容,另一個用于編譯腳本?
- 我希望在編譯期間觸發
exec:exec
,如果不是,則在 WAR 打包之前觸發.我該怎么做?
- How can I extract different portions of a single zipped dependency for the compilation and WAR packaging steps? Or do I have to create two zip files, one with just the runtime stuff and the other for compilations scripts?
- I would like to trigger
exec:exec
ideally during compilation, or if not, just prior to WAR packaging. How do I do that?
我實際上已經嘗試了很多沒有成功的東西,所以我希望我不會顯得懶惰地發布大量代碼并等待答案:) 只是我還沒有完全理解 Maven 是如何實現的目標/階段等工作還沒有.
I have actually tried a bunch off stuff without success, so I hope I don't appear as lazily posting a huge chunk of code and waiting for answers :) It's just that I haven't quite wrapped my mind around how Maven targets/phases etc. work yet.
推薦答案
我想出了以下適合我的解決方案:
I've come up with the following solution that works for me:
我沒有依賴 WAR 覆蓋來解壓 RequireJS 文件,而是使用 Dependency 插件顯式解壓它們:
Instead of depending on the WAR overlay for the unpacking of the RequireJS files, I explicitly unpack them using the Dependency plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.requirejs</groupId>
<artifactId>requirejs</artifactId>
<version>0.22.0</version>
<type>zip</type>
<classifier>repackaged</classifier>
<overWrite>true</overWrite>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
階段設置為編譯".這允許我在編譯期間擁有依賴"文件夾下的 RequireJS 包的全部內容.所以,接下來我要做的是:
The phase is set to "compile". This allows me to have the entire contents of the RequireJS package under the "dependency" folder, during compilation. So, the next thing I have is:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>
${project.build.directory}/dependency/requirejs/build/build.bat</executable>
<workingDirectory>
${basedir}/src/main/webapp</workingDirectory>
<arguments>
<argument>name=bootstrap</argument>
<argument>out=scripts/compiled.js</argument>
<argument>baseUrl=scripts</argument>
<argument>optimize=closure</argument>
<argument>
excludeShallow=plugins/manifest</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
這會觸發依賴"文件夾內的 RequireJS 編譯,而無需觸及我的源目錄或 WAR 目錄.然后我繼續使用 WAR 覆蓋插件來挑選想要進入 WAR 的 RequireJS 文件.
This triggers RequireJS compilation inside the "dependency" folder, without touching either my source directory or the WAR directory. I then continue using the WAR overlay plugin to cherry pick the RequireJS files that want to go into the WAR.
更新
自從編寫此解決方案以來,我已切換到使用java"目標而不是exec",因為我在通過 Hudson 使用 RequireJS 編譯器的 shell 腳本 + 批處理文件時遇到了問題.我基本上是在運行通過 Rhino 運行編譯器的最終 Java 命令(由腳本生成).Node 解決方案會略有不同.對于 RequireJS 0.23.0,它是這樣的:
Since writing this solution, I've switched to using the "java" goal instead of "exec" because I had problems with using the RequireJS compiler's shell script + batch file through Hudson. I'm basically running the final Java command (generated by the scripts) that run the compiler through Rhino. The Node solution would be slightly different. For RequireJS 0.23.0, it goes something like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>compile-js</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>java</executable>
<workingDirectory>${basedir}/src/main/webapp</workingDirectory>
<arguments>
<argument>-classpath</argument>
<!--argument>${project.build.directory}/dependency/requirejs/build/lib/rhino/js.jar${path.separator}${project.build.directory}/dependency/requirejs/build/lib/closure/compiler.jar</argument -->
<argument>${project.build.directory}/dependency/requirejs/build/lib/rhino/js.jar</argument>
<argument>org.mozilla.javascript.tools.shell.Main</argument>
<argument>${project.build.directory}/dependency/requirejs/bin/x.js</argument>
<argument>${project.build.directory}/dependency/requirejs/bin/</argument>
<argument>${project.build.directory}/dependency/requirejs/build/build.js</argument>
<argument>name=bootstrap</argument>
<argument>out=scripts/compiled.js</argument>
<argument>baseUrl=scripts</argument>
<argument>optimize=none</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
這篇關于Maven項目中的RequireJS編譯與外部JS依賴的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!