GRADLE 任务 运行 配置

GRADLE tasks run configuration

我有一个由两部分组成的项目:Spring Boot 和 React。 在我的 Spring 引导 build.gradle 配置中,我指定了应该执行哪些操作才能构建和 运行 应用程序。

这是它的样子:

plugins {
    id 'org.springframework.boot' version '2.2.5.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
  id "com.github.node-gradle.node" version "2.2.4"
}

group = 'com.vtti'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
  implementation 'org.apache.poi:poi:3.10-FINAL'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
        compile 'org.apache.poi:poi:3.10-FINAL'
        compile 'org.apache.poi:poi-ooxml:3.10-FINAL'
        compile 'com.sendgrid:sendgrid-java:4.1.2'
        compile 'org.json:json:20190722'
        compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.11.0'
}

test {
    useJUnitPlatform()
}

node {
  // Version of node to use.
  version = '10.16.3'
  // Version of Yarn to use.
  yarnVersion = '1.21.1'

  // Base URL for fetching node distributions (change if you have a mirror).
  distBaseUrl = 'https://nodejs.org/dist'

  // If true, it will download node using above parameters.
  // If false, it will try to use globally installed node.
  download = true

  // Set the work directory for unpacking node
  workDir = file("${project.buildDir}/nodejs")
  // Set the work directory for YARN
  yarnWorkDir = file("${project.buildDir}/yarn")
  // Set the work directory where node_modules should be located
  nodeModulesDir = file("${project.projectDir}")
}


task appYarnInstall(type: YarnTask) {
  description = "Install all dependencies from package.json"
  workingDir = file("${project.projectDir}/src/main/client")
  args = ["install"]
}

task appYarnBuild(type: YarnTask) {
  description = "Build production version of the React client"
  workingDir = file("${project.projectDir}/src/main/client")
  args = ["run", "build"]
}

task copyClient(type: Copy) {
  from 'src/main/client/build'
  // into 'build/resources/main/static/.'
  into 'src/main/resources/static/.'
}

appYarnBuild.dependsOn appYarnInstall
copyClient.dependsOn appYarnBuild
compileJava.dependsOn copyClient

当我运行gradlew build一切正常时,Gradle执行yarn installyarn build

然而,当我 运行 gradlew bootRun 并且只想编译和 运行 一个项目时,它会再次执行所有 yarn 操作并构建一个新的前端 -结束,这导致 git 可见的多个“已更改文件”,应再次提交。

是否可以指定任务何时 运行 和 运行 它们仅在 gradlew build 而不是 gradlew bootRun 上?

您可以使用 -x 命令行选项并提供要排除的任务的名称来排除正在执行的任务。

例如 gradle bootRun -x appYarnInstall

之前有人问过这个问题,但在您的具体情况下,这可能是您要查找的内容:

gradle.taskGraph.whenReady { graph ->
  if (graph.hasTask(bootRun)) {
    tasks.withType(YarnTask){
      enabled = false
    }
  }
}

这样的问题经常出现,而答案几乎总是治标不治本。大多数解决方案将包括以下 Gradle 功能之一:

  • 命令行选项 -x 或其等效程序 gradle.startParameter.excludedTaskNames
  • 直接访问gradle.taskGraph
  • 任务的onlyIf子句

在大多数情况下,这些解决方案实际上是肮脏的黑客攻击,以后可能适得其反。

很多情况下的实际问题是以错误的方式配置和连接的任务。 Gradle 世界中的一个常见误解是认为只有少数任务可以从命令行调用。基于这个假设,整个构建脚本都是围绕这些任务设计的(通常只有来自 Java 插件的任务 build)。在这些情况下,整个构建脚本由 dependsOn 语句组成,这些语句在 gradle build 被调用时以某种方式以正确的顺序执行任务。您关注命令(而不是任务)gradlew buildgradlew bootRun 的问题显示了相同的问题:

Is that possible to specify when tasks should be run and run them only on gradlew build and not on gradlew bootRun?

一个更好的问题是:

Is it possible to run the tasks appYarnInstall and appYarnBuild only when they need to run?

正如您在问题中所解释的,实际问题是由任务 运行 再次 引起的。所以,也许我们应该弄清楚他们什么时候需要 运行?如果我理解你的项目结构正确,有两种情况他们需要 运行:

  • 如果前端根本不存在(例如在新结帐时)
  • 如果部分前端源文件发生变化

现在您可以在您的构建脚本中实现这个逻辑,但是 Gradle 提供了开箱即用的 incremental build support。您只需要定义创建文件的任务的输入和输出,Gradle 将确定任务何时需要 运行。

由于我不完全了解您的哪些任务处理哪些文件(而且我不熟悉 Gradle Node 插件),因此我很难为您提供一个完整的构建脚本,但让我给你一些提示:

  • 不要将 Gradle 处理的源目录与 Node 或 Yarn 等外部系统处理的源目录混合。 workingDir hack 变得很有必要,因为这些工具需要另一个存储库布局。在您当前的设置中,任务结果最终位于源目录中 (src/main/client/build)。

  • 不要使用 Copy 类型的任务。相反,定义任务 appYarnBuild 的输出并将此任务用作 processResources 的附加输入。这也消除了您的任务对 compileJava.

    的依赖
  • 始终将任务的结果存储在 buildDir 中,而不是 src 的子文件夹中。这样您就可以始终使用 gradle clean build 创建干净的构建。如果任务在 src 中创建文件,它们将不会在 clean 期间被删除,并且可能会在以后的构建中导致问题。