使用外部JS依赖关系在Maven项目中进行RequireJS编译 [英] RequireJS Compilation in Maven project with external JS dependencies

查看:145
本文介绍了使用外部JS依赖关系在Maven项目中进行RequireJS编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Maven构建的Web项目,我试图找出使用RequireJS编译器编译JavaScript文件的最佳方式(此问题也可以应用于任何编译器/分解器)。



我有一个工作的设置,但它需要改进:



我打包了第三方JavaScript库,他们是作为依赖关系下载,然后添加了WAR Overlay插件。



我有一个Exec插件任务,在目标目录中运行RequireJS编译器。在目标运行后,我目前手动运行 exec:exec 。因此,WAR内容放在目标目录中。



我想要的是使JS编译成主(Java)编译的一部分。在编译之后发生的WAR覆盖阶段,JS编译器本身(Require JS)被下载为依赖关系。所以,我需要下载和解压缩需求的JS文件,我需要在Java编译之前/期间/之后使用这些文件运行JS编译。



确保可以有几种方法来实现这一点。我正在寻找最优雅的解决方案。






更新:现有的POM片段 p>

我有JavaScript依赖关系,我已压缩并添加到我们的存储库管理器中:

 <依赖性> 
< groupId> org.requirejs< / groupId>
< artifactId> requirejs< / artifactId>
< version> 0.22.0< / version>
< classifier>重新打包< / classifier>
< type> zip< / type>
< scope>运行时< / scope>
< / dependency>
<依赖关系>
< groupId> com.jqueryui< / groupId>
< artifactId> jquery-ui< / artifactId>
< version> 1.8.7< / version>
< classifier>重新打包< / classifier>
< type> zip< / type>
< scope>运行时< / scope>
< / dependency>请注意,RequireJS本身(这是其余的库的编译所必需的)也被加载到


作为外部依赖。所以第一件事是,我需要下载并解压缩它,然后才能开始使用RequireJS编译。



这些依赖关系正在使用WAR Overlay添加到WAR中插件:

 < plugin> 
< artifactId> maven-war-plugin< / artifactId>
< configuration>
< overlayays>
< overlay>
< groupId> org.requirejs< / groupId>
< artifactId> requirejs< / artifactId>
< classifier>重新打包< / 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>重新打包< / classifier>
< type> zip< / type>
< targetPath> lib< / targetPath>
< / overlay>
< / overlays>
< / configuration>
< / plugin>

即使我不需要 requirejs / build / ** 最终在WAR中,我将其作为覆盖图的一部分,以获得解压缩的RequireJS构建脚本,这仅仅是因为我没有想到更好的方法。



然后我有一个执行编译的Exec插件任务。但请注意,此任务尚未添加到正常的编译工作流程中:我必须手动调用它,使用 mvn exec:exec 之后 WAR包装完成:

 < plugin> 
< groupId> org.codehaus.mojo< / groupId>
< artifactId> exec-maven-plugin< / artifactId>
< version> 1.1< / version>
<执行>
< 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包装之前。我如何做到这一点?

  • 我实际上尝试了一些东西,没有成功,所以我希望我不会像懒洋洋的发布一大堆代码,等待答案:)只是我没有把我的想法围绕着Maven的目标/阶段等工作。

    解决方案

    我已经提出了以下适用于我的解决方案:



    而不是依赖于WAR打包RequireJS文件,我使用Dependency插件显式解压缩它们:

     < plugin> 
    < groupId> org.apache.maven.plugins< / groupId>
    < artifactId> maven-dependency-plugin< / artifactId>
    <执行>
    < 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>重新打包< / classifier>
    < overWrite> true< / overWrite>
    < / artifactItem>
    < / artifactItems>
    < / configuration>
    < / execution>
    < / executions>
    < / plugin>

    阶段设置为编译。这使我可以在编译期间将RequireJS包的所有内容都放在依赖关系文件夹下。所以,我下一件事是:

     < plugin> 
    < groupId> org.codehaus.mojo< / groupId>
    < artifactId> exec-maven-plugin< / artifactId>
    < version> 1.1< / version>
    <执行>
    < 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文件。



    更新



    自编写这个解决方案以来,我已经切换到使用java目标而不是exec,因为我在Hudson中使用RequireJS编译器的shell脚本+批处理文件有问题。我基本上运行了通过Rhino运行编译器的最终Java命令(由脚本生成)。 Node解决方案会略有不同。对于RequireJS 0.23.0,它是这样的:

     < plugin> 
    < groupId> org.codehaus.mojo< / groupId>
    < artifactId> exec-maven-plugin< / artifactId>
    < version> 1.1< / version>
    <执行>
    < 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} /依赖项/ requirejs / build / lib / closure / compiler.jar< / argument - >
    < arguments> $ {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>


    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:

    I've packaged the 3rd party JavaScript libraries and they are being downloaded 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 currently manually run exec:exec after the package target runs (and therefore the WAR contents are placed in the target directory).

    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.


    Update: Existing POM snippets

    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>
    

    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.

    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>
    

    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.

    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>
    

    So, some questions are:

    1. 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?
    2. I would like to trigger exec:exec ideally during compilation, or if not, just prior to WAR packaging. How do I do that?

    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:

    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>
    

    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>
    

    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.

    Update

    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>
    

    这篇关于使用外部JS依赖关系在Maven项目中进行RequireJS编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆