我有一个包含两个部分的项目: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 install
,yarn build
等。
但是,当我运行gradlew bootRun
并只希望编译和运行项目时,它将再次执行所有yarn
动作并构建一个新的前端,这会导致多个“更改的文件”对于git可见,应该再次提交。
是否可以指定何时应运行任务,并仅在gradlew build
而不是gradlew bootRun
上运行任务?
答案 0 :(得分:2)
这样的问题经常出现,答案几乎总是针对症状而不是实际原因。大多数解决方案将包括以下Gradle功能之一:
-x
或与程序等效的gradle.startParameter.excludedTaskNames
gradle.taskGraph
onlyIf
子句在大多数情况下,这些解决方案实际上是肮脏的hack,以后可能会适得其反。
在许多情况下,实际问题是任务配置和连接方式错误。在Gradle世界中,一个常见的误解是认为只有少数几个任务可以从命令行调用。基于此假设,整个构建脚本都是围绕这些任务(通常仅是Java插件中的任务build
)设计的。在这些情况下,整个构建脚本由dependsOn
条语句组成,这些语句在调用gradle build
时以正确的顺序执行任务。您的问题集中在命令(而不是任务)gradlew build
和gradlew bootRun
上,它显示了相同的问题:
是否可以指定何时应运行任务,并且仅在
gradlew build
而不是gradlew bootRun
上运行它们?
一个更好的问题是:
是否可以仅在任务
appYarnInstall
和appYarnBuild
需要运行时运行它们?
正如您在问题中解释的那样,实际问题是由任务再次运行而造成的。因此,也许我们应该弄清楚它们何时需要运行?如果我正确理解您的项目结构,则有两种情况需要运行它们:
现在您可以在构建脚本中实现此逻辑,但是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
}
}
}