Skip to content

Commit beaed7c

Browse files
authored
refactor!: stop auto-running vaadinPrepareFrontend in development mode (#24119)
IDE-triggered Gradle builds (e.g. IntelliJ compiling on file change) were running `vaadinPrepareFrontend` via `processResources`, which interfered with the running Vite dev server and broke hotdeploy. Since Vaadin 25, the dev server handles frontend preparation at runtime, so the task no longer needs to run automatically. The previous behavior can be restored by setting `alwaysExecutePrepareFrontend = true`. Fixes #24108
1 parent 6b1d622 commit beaed7c

File tree

5 files changed

+63
-38
lines changed

5 files changed

+63
-38
lines changed

flow-plugins/flow-gradle-plugin/src/functionalTest/kotlin/com/vaadin/gradle/MiscSingleModuleTest.kt

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -283,21 +283,20 @@ class MiscSingleModuleTest : AbstractGradleTest() {
283283

284284
val build: BuildResult =
285285
testProject.build("-Pvaadin.productionMode=false", "bootJar")
286-
build.expectTaskSucceded("vaadinPrepareFrontend")
286+
build.expectTaskNotRan("vaadinPrepareFrontend")
287287
build.expectTaskNotRan("vaadinBuildFrontend")
288288

289289
val jar: File = testProject.builtJar
290290
expectArchiveDoesntContainVaadinBundle(jar, false)
291291
}
292292

293293
private fun doTestSpringProject() {
294-
val springBootVersion = "3.3.4"
294+
val springBootVersion = "4.0.5"
295295

296296
testProject.settingsFile.writeText(
297297
"""
298298
pluginManagement {
299299
repositories {
300-
maven { url 'https://repo.spring.io/milestone' }
301300
gradlePluginPortal()
302301
}
303302
}
@@ -307,35 +306,27 @@ class MiscSingleModuleTest : AbstractGradleTest() {
307306
"""
308307
plugins {
309308
id 'org.springframework.boot' version '$springBootVersion'
310-
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
309+
id 'io.spring.dependency-management' version '1.1.7'
311310
id 'java'
312311
id("com.vaadin.flow")
313312
}
314-
313+
315314
repositories {
316315
mavenLocal()
317316
mavenCentral()
318317
maven { url 'https://maven.vaadin.com/vaadin-prereleases' }
319-
maven { url 'https://repo.spring.io/milestone' }
320318
}
321319
322-
configurations {
323-
developmentOnly
324-
runtimeClasspath {
325-
extendsFrom developmentOnly
326-
}
327-
}
328-
329320
dependencies {
330321
implementation('com.vaadin:flow:$flowVersion')
331322
implementation('com.vaadin:vaadin-spring:$flowVersion')
332-
implementation('org.springframework.boot:spring-boot-starter-web:$springBootVersion')
323+
implementation('org.springframework.boot:spring-boot-starter-webmvc:$springBootVersion')
333324
developmentOnly 'org.springframework.boot:spring-boot-devtools'
334325
testImplementation('org.springframework.boot:spring-boot-starter-test') {
335326
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
336327
}
337328
}
338-
329+
339330
dependencyManagement {
340331
imports {
341332
mavenBom "com.vaadin:flow:$flowVersion"
@@ -564,6 +555,34 @@ class MiscSingleModuleTest : AbstractGradleTest() {
564555
}
565556
}
566557

558+
@Test
559+
fun alwaysExecutePrepareFrontend_chainsToProcessResources() {
560+
testProject.buildFile.writeText(
561+
"""
562+
plugins {
563+
id 'war'
564+
id 'com.vaadin.flow'
565+
}
566+
repositories {
567+
mavenLocal()
568+
mavenCentral()
569+
maven { url = 'https://maven.vaadin.com/vaadin-prereleases' }
570+
}
571+
dependencies {
572+
implementation("com.vaadin:flow:$flowVersion")
573+
providedCompile("jakarta.servlet:jakarta.servlet-api:6.0.0")
574+
implementation("org.slf4j:slf4j-simple:$slf4jVersion")
575+
}
576+
vaadin {
577+
alwaysExecutePrepareFrontend = true
578+
}
579+
"""
580+
)
581+
val build: BuildResult = testProject.build("build")
582+
build.expectTaskSucceded("vaadinPrepareFrontend")
583+
build.expectTaskNotRan("vaadinBuildFrontend")
584+
}
585+
567586
@Test
568587
fun testIncludeExclude() {
569588
testProject.buildFile.writeText("""
@@ -614,17 +633,17 @@ class MiscSingleModuleTest : AbstractGradleTest() {
614633
"""
615634
plugins {
616635
id 'java'
617-
id 'org.springframework.boot' version '3.3.4'
618-
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
636+
id 'org.springframework.boot' version '4.0.5'
637+
id 'io.spring.dependency-management' version '1.1.7'
619638
id("com.vaadin.flow")
620639
}
621-
640+
622641
repositories {
623642
mavenLocal()
624643
mavenCentral()
625644
maven { url 'https://maven.vaadin.com/vaadin-prereleases' }
626645
}
627-
646+
628647
sourceSets {
629648
ui {
630649
java
@@ -636,15 +655,15 @@ class MiscSingleModuleTest : AbstractGradleTest() {
636655
}
637656
}
638657
}
639-
658+
640659
vaadin {
641660
productionMode = true
642661
sourceSetName = 'ui'
643662
}
644-
663+
645664
dependencies {
646665
uiImplementation('com.vaadin:flow:$flowVersion')
647-
implementation('org.springframework.boot:spring-boot-starter-web')
666+
implementation('org.springframework.boot:spring-boot-starter-webmvc')
648667
}
649668
650669
jar {

flow-plugins/flow-gradle-plugin/src/functionalTest/kotlin/com/vaadin/gradle/TestUtils.kt

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ fun expectArchiveContainsVaadinBundle(
176176
/**
177177
* Asserts that given archive (jar/war) doesn't contain the Vaadin bundle:
178178
* the `META-INF/VAADIN/build/` directory.
179+
*
180+
* Since Vaadin 25, `vaadinPrepareFrontend` is no longer auto-triggered in
181+
* development mode, so the token file (`flow-build-info.json`) is not
182+
* expected in the archive.
179183
*/
180184
fun expectArchiveDoesntContainVaadinBundle(archive: File,
181185
isSpringBootJar: Boolean) {
@@ -186,8 +190,8 @@ fun expectArchiveDoesntContainVaadinBundle(archive: File,
186190
isSpringBootJar -> "BOOT-INF/classes/"
187191
else -> ""
188192
}
189-
expectArchiveContains("${resourcePackaging}META-INF/VAADIN/config/flow-build-info.json") { archive }
190-
expectArchiveDoesntContain("${resourcePackaging}META-INF/VAADIN/config/stats.json",
193+
expectArchiveDoesntContain("${resourcePackaging}META-INF/VAADIN/config/flow-build-info.json",
194+
"${resourcePackaging}META-INF/VAADIN/config/stats.json",
191195
"${resourcePackaging}META-INF/VAADIN/webapp/VAADIN/build/*.gz",
192196
"${resourcePackaging}META-INF/VAADIN/webapp/VAADIN/build/*.js"
193197
) { archive }
@@ -196,12 +200,6 @@ fun expectArchiveDoesntContainVaadinBundle(archive: File,
196200
val libPrefix: String = if (isSpringBootJar) "BOOT-INF/lib" else "WEB-INF/lib"
197201
expectArchiveContains("$libPrefix/*.jar") { archive }
198202
}
199-
200-
// make sure there is only one flow-build-info.json
201-
val allFiles: List<String> = archive.zipListAllFiles()
202-
expect(1, "Multiple flow-build-info.json found: ${allFiles.joinToString("\n")}") {
203-
allFiles.count { it.contains("flow-build-info.json") }
204-
}
205203
}
206204

207205
/**

flow-plugins/flow-gradle-plugin/src/functionalTest/kotlin/com/vaadin/gradle/VaadinSmokeTest.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ class VaadinSmokeTest : AbstractGradleTest() {
7878
}
7979

8080
@Test
81-
fun `vaadinBuildFrontend not ran by default in development mode`() {
81+
fun `vaadin tasks not ran by default in development mode`() {
8282
val result: BuildResult = testProject.build("build")
83-
// let's explicitly check that vaadinPrepareFrontend has been run.
84-
result.expectTaskOutcome("vaadinPrepareFrontend", TaskOutcome.SUCCESS)
85-
// vaadinBuildFrontend should NOT have been executed automatically
83+
// Since Vaadin 25, the dev server handles frontend preparation at
84+
// runtime, so no vaadin tasks are chained to the build in dev mode.
85+
result.expectTaskNotRan("vaadinPrepareFrontend")
8686
result.expectTaskNotRan("vaadinBuildFrontend")
8787

8888
val build = File(testProject.dir, "build/resources/main/META-INF/VAADIN/webapp/VAADIN/build")

flow-plugins/flow-gradle-plugin/src/main/kotlin/com/vaadin/gradle/FlowPlugin.kt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,16 @@ public class FlowPlugin : Plugin<Project> {
8383
svc?.ensureToken()
8484
}
8585
}
86-
} else {
87-
// In development mode, processResources copies stuff from
88-
// build/vaadin-generated (which is populated by
89-
// vaadinPrepareFrontend) and therefore must run after it.
86+
} else if (config.alwaysExecutePrepareFrontend.get()) {
87+
// In development mode, vaadinPrepareFrontend is not
88+
// auto-triggered by default. Since Vaadin 25, the dev
89+
// server handles frontend preparation at runtime, so
90+
// running the task during every IDE-triggered build is
91+
// unnecessary and can interfere with the running Vite
92+
// dev server.
93+
// However, if alwaysExecutePrepareFrontend is set,
94+
// restore the old behavior and chain the task to
95+
// processResources.
9096
project.tasks.getByPath(config.processResourcesTaskName.get()).dependsOn("vaadinPrepareFrontend")
9197
}
9298

flow-plugins/flow-gradle-plugin/src/main/kotlin/com/vaadin/gradle/VaadinFlowPluginExtension.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ public abstract class VaadinFlowPluginExtension @Inject constructor(private val
300300
* will re-run every time it is called.
301301
*
302302
* Setting this to `true` allows to always execute `vaadinPrepareFrontend`.
303+
* It also chains the task to `processResources`, which is no longer done
304+
* by default since the dev server handles frontend preparation at runtime.
303305
*
304306
* Defaults to `false`, meaning that the task execution is skipped when its
305307
* outcomes are up-to-date, improving the overall build time.

0 commit comments

Comments
 (0)