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 install
、yarn 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 build
和 gradlew 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
期间被删除,并且可能会在以后的构建中导致问题。
我有一个由两部分组成的项目: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 install
、yarn 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 build
和 gradlew bootRun
的问题显示了相同的问题:
Is that possible to specify when tasks should be run and run them only on
gradlew build
and not ongradlew bootRun
?
一个更好的问题是:
Is it possible to run the tasks
appYarnInstall
andappYarnBuild
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
期间被删除,并且可能会在以后的构建中导致问题。