具有外部 JS 依赖的 Maven 项目中的 RequireJS 编译

发布于 2024-10-11 09:14:29 字数 4448 浏览 6 评论 0原文

我有一个使用 Maven 构建的 Web 项目,我试图找出使用 RequireJS 编译器编译 JavaScript 文件的最佳方法(这个问题也适用于任何编译器/压缩器)。

我有一个有效的设置,但需要改进:

我已经打包了第 3 方 JavaScript 库,它们作为依赖项下载,然后使用 WAR Overlay 插件添加。

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

我想要的是让 JS 编译成为主(Java)编译的一部分。 JS 编译器本身 (Require JS) 在编译后发生的 WAR 覆盖阶段作为依赖项下载。因此,我需要下载并解压 Require JS 文件,并且需要在 Java 编译之前/期间/之后使用这些文件运行 JS 编译。

我确信可以通过多种方法来实现这一目标。我正在寻找最优雅的解决方案。


更新:现有的 POM 片段

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

    <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 编译。

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

        <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 构建脚本,只是因为我还没有找到更好的方法。

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

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

所以,一些问题是:

  1. 如何提取单个压缩依赖项的不同部分以进行编译和 WAR 打包步骤?或者我是否必须创建两个 zip 文件,一个仅包含运行时内容,另一个用于编译脚本?
  2. 我希望在编译期间触发 exec:exec ,或者如果没有,则在 WAR 打包之前触发。我该怎么做?

我实际上已经尝试了很多东西但没有成功,所以我希望我不会显得懒惰地发布大量代码并等待答案:)只是我还没有完全理解 Maven 的目标/阶段等等工作还没有。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

两仪 2024-10-18 09:14:29

有一个专门针对 RequireJS 优化的 Maven 插件:

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

它应该始终附带最新版本的 RequireJS,并且通过向项目添加不同版本并在插件配置中指定它的路径来覆盖它非常容易。

完全披露:我写了这个插件。

There's a maven plugin specifically targeted for RequireJS optimization at:

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

It should always ship with a recent version of RequireJS, and it's pretty easy to override that by adding a different version to your project, and specifying it's path in the plugin config.

Full disclosure: I wrote the plugin.

全部不再 2024-10-18 09:14:29

我提出了以下适合我的解决方案:

我不依赖 WAR 覆盖来解包 RequireJS 文件,而是使用 Dependency 插件显式解包它们:

  <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 包的全部内容放在“dependency”文件夹下。所以,我要做的下一件事是:

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

这会触发“dependency”文件夹内的 RequireJS 编译,而不会触及我的源目录或 WAR 目录。然后,我继续使用 WAR 覆盖插件来挑选想要进入 WAR 的 RequireJS 文件。

更新

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

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

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文