-
Notifications
You must be signed in to change notification settings - Fork 192
Description
Problem
vaadinBuildFrontend writes Vite output to build/resources/main/META-INF/VAADIN/webapp/ — the same directory owned by Gradle's processResources. Gradle's overlapping-outputs validation prevents declaring this as a task @OutputDirectory. Without declared outputs:
- Local up-to-date check works (with
@CacheableTask+@Inputfrom PR feat: BuildFrontend Incremental build #23884) - Build cache restore does not — Gradle skips the task on a cache hit but doesn't restore the frontend files. The jar ships without
index.htmland the app crashes at runtime.
This is the CI use case — the one that matters most for build performance.
Discussed in #17354 — @mcollovati suggested opening a dedicated ticket.
Root cause
servletResourceOutputDirectory() in GradlePluginAdapter is hardcoded to build/resources/main/META-INF/VAADIN/ (when isBeforeProcessResources=false), and frontendOutputDirectory in VaadinFlowPluginExtension defaults to a subdirectory of it. This puts both inside processResources territory.
ProdBundleUtils.compressBundle() reads from servletResourceOutputDirectory, so redirecting frontendOutputDirectory alone breaks the bundle — both need to move together.
Proposed fix
- Change the default
frontendOutputDirectoryto a non-conflicting path — e.g.build/vaadin-frontend/META-INF/VAADIN/webapp/ - Move
servletResourceOutputDirectoryalongside it (or derive it from the same base) - Declare
frontendOutputDirectoryas@OutputDirectoryonVaadinBuildFrontendTask - Wire the plugin to automatically add a
from(frontendOutputDirectory)to the jar task so the files end up on the classpath
This preserves the existing behavior (files end up at META-INF/VAADIN/webapp/ in the jar) while letting Gradle's build cache do its job.
Impact
We measured the difference on our project (Vaadin 24.9.12, ~42 JS chunks):
| Scenario | Time |
|---|---|
| Cache miss (Vite runs) | ~26s |
| Cache hit (task skipped) | ~5s |
| Saved | ~21s per build |
On GitHub Actions with persistent runners: build step dropped from ~116s to ~54s.
Our workaround (for anyone stuck on 24.x)
We declare src/main/bundles/ as the task output (contains prod.bundle), then zipTree() it in the jar task into META-INF/VAADIN/. We're unzipping the zip that compressBundle() created from the files we can't cache directly. Details: https://github.com/galateatech/waste-coordinator/pull/10283
Happy to contribute a PR if the team can confirm the approach direction.
Environment
- Vaadin: 24.9.12
- Gradle: 9.3.1
- Also reviewed 25.0 source — same issue persists after PR feat: BuildFrontend Incremental build #23884