GRADLE任务运行配置

时间:2020-07-09 15:25:45

标签: java reactjs spring gradle build.gradle

我有一个包含两个部分的项目:Spring Boot和React。 在我的Spring Boot 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上运行任务?

3 个答案:

答案 0 :(得分:2)

这样的问题经常出现,答案几乎总是针对症状而不是实际原因。大多数解决方案将包括以下Gradle功能之一:

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

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

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

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

一个更好的问题是:

是否可以仅在任务appYarnInstallappYarnBuild需要运行时运行它们?

正如您在问题中解释的那样,实际问题是由任务再次运行而造成的。因此,也许我们应该弄清楚它们何时需要运行?如果我正确理解您的项目结构,则有两种情况需要运行它们:

  • 如果前端根本不存在(例如在新结帐时)
  • 如果某些前端源文件已更改

现在您可以在构建脚本中实现此逻辑,但是Gradle会使用incremental build support来提供此逻辑。您只需要定义创建文件的任务的输入和输出,Gradle就会确定何时需要运行任务。

由于我不完全了解您的任务中的哪些会处理哪些文件(并且我对Gradle Node插件不熟悉),因此很难为您提供一个可以正常工作的构建脚本,但我还是给您一个一些提示:

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

  • 请勿使用Copy类型的任务。而是定义任务appYarnBuild的输出,并将此任务用作processResources的附加输入。这也消除了您对compileJava的任务依赖性。

  • 始终将任务的结果存储在buildDir内,而不存储在src的子文件夹中。这样,您可以始终使用gradle clean build创建一个干净的内部版本。如果任务在src中创建文件,则它们不会在clean期间删除,并且可能在以后的版本中引起问题。

答案 1 :(得分:1)

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

例如 gradle bootRun -x appYarnInstall

答案 2 :(得分:0)

这个问题曾经被问过,但是在您的特定情况下,这可能是您要寻找的内容:

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