Compiling RequireJS in a Maven project with external JS dependencies

I have a web project built using Maven, and I'm trying to find a better way to compile JavaScript files using the RequireJS compiler (this question can apply to any / minifier compiler as well).

I have a setting that works, but it needs to be improved:

I have packaged third-party JavaScript libraries and they are loaded as dependencies and then added with the WAR Overlay plugin.

I have an exec plugin task that runs the RequireJS compiler inside the target directory. I am currently running manually exec:exec after running the target (and therefore the contents of the WAR are placed in the target directory).

Instead, I would like to make the JS compilation part of the main (Java) compilation. The JS compiler (Require JS) itself is loaded as a dependency during the WAR overlay phase that occurs after compilation. So, I need the required JS files to be downloaded and unpacked, and I need to start compiling JS using these files before / during / after compiling Java.

I am sure there can be several ways to do this. I am looking for the most elegant solution.




Update: Existing POM Snippets

I have JavaScript dependencies that I pinned 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> 

Note that RequireJS itself (which is required to compile the rest of the libraries) also loads as an external dependency. So, firstly, I need this dependency to load and unpack before I start compiling RequireJS.

These dependencies are added to 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> 

Although I do not need requirejs/build/** to complete the WAR, I include it as part of the overlay to get the Unpacked RequireJS build scripts unpacked, simply because I did not understand a better way.

Then I have an exec plugin task that compiles. But keep in mind that this task was not added to the normal compilation workflow: I need to manually call it using mvn exec:exec after packing the WAR:

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

So, some questions:

  • How can I extract the different parts of one archived dependency for compilation and WAR assembly steps? Or do I need to create two zip files, one with a runtime file, and the other for compilation scripts?
  • I would like to include exec:exec ideally at compile time, and if not, before packing the WAR. How to do it?

I actually tried a bunch of things without success, so I hope that I don’t appear as lazily laying out a huge piece of code and waiting for answers :) It's just that I didn’t quite turn around like Maven goals / phases, etc.

+19
javascript maven requirejs dependencies
Jan 11 2018-11-11T00:
source share
3 answers

I came up with the following solution that works for me:

Instead of relying on a WAR overlay to decompress the RequireJS files, I explicitly decompress 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> 

The phase is set to "compile". This allows me at compile time to load the contents of the RequireJS package into the dependency folder. So the following is what I have:

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

This causes RequireJS to compile inside the dependency folder, without affecting either my source directory or the WAR directory. Then I continue to use the WAR overlay plugin for cherries to select RequireJS files that want to enter the WAR.

Update

Since writing this solution, I switched to using the java target instead of exec because I had problems using the RequireJS script compiler shell + batch file through Hudson. I basically run the last Java command (generated by scripts) that runs the compiler through Rhino. Node's solution will be slightly different. For RequireJS 0.23.0, it looks 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> 
+4
Jan 19 '11 at 3:17
source share
+8
Feb 23 '11 at 11:26
source share

There, the maven plugin is specifically designed to optimize RequireJS:

https://github.com/mcheely/requirejs-maven-plugin

It should always come with the latest version of RequireJS, and it's pretty easy to override this by adding another version to the project and specifying its path in the plugin configuration.

Full disclosure: I wrote a plugin.

+6
Jul 19 '12 at 4:23
source share



All Articles