Releases: vaadin/flow
Release list
Vaadin Flow 25.3.0-alpha7
Changes since 25.3.0-alpha6
Breaking changes
-
Do not use serveStaticOrWebJarRequest
Commit · Pull requestDeprecate the serverStaticOrWebJarRequest method and directly use the serveStaticResource from staticFileHandler. No rename or direct removal for the protected method. Closes #8944
New features
-
Add HasAriaDescription interface
Commit · Pull requestAdds a
HasAriaDescriptionmixin interface for setting the accessible description of a component, following theHasAriaLabelpattern: -setAriaDescription(String)/getAriaDescription()for thearia-descriptionattribute -setAriaDescribedBy(String)/getAriaDescribedBy()for thearia-describedbyattribute -setAriaDescribedBy(Component)for referencing a description component directly, generating an id for it lazily when needed (same mechanism assetAriaLabelledBy(Component)) Also adds thearia-descriptionandaria-describedbyattribute name constants toElementConstants. Part of vaadin/web-components#11975 -
Unify deletion and add message
Commit · Pull requestUnify file and folder deletions and add a clear message that gives hint on what to do when a file deletion fails. Symlinks and junctions are now handled for all deletions. deleteIfExists should use deleteSingle method to get the helper exception. Closes #7373
Fixes
-
Read minimum frontend package age from config in dev mode
Commit · Pull requestThe dev mode initializer built the frontend Options without reading the npm.minimumFrontendPackageAgeDays property, so the minimum package age check was ignored at runtime and always fell back to the Options default of one day. The Maven build path already wired this through, making dev mode inconsistent with the build. Read the property in DevModeInitializer and pass it to the Options via withMinimumFrontendPackageAgeDays.
-
Collect frontend dependencies of dev tools message handlers
Commit · Pull requestFrontendDependencies resolves DevToolsMessageHandler subtypes to add them as internal entry points, but the class was missing from the
@HandlesTypesof DevModeStartupListener. DevModeClassFinder only knows the classes listed there and throws for anything else, and that exception was swallowed by the surrounding catch block intended for a missing dev tools classpath entry. As a result, frontend dependencies declared by dev tools plugins were silently skipped in development mode when the byte-code scanner is enabled. -
Do not reinstall packages when pnpm reformats its workspace file
Commit · Pull request · IssuePnpmWorkspaceFile.save() compared the serialized text of pnpm-workspace.yaml against the file on disk. pnpm rewrites that file while installing, in its own formatting, so the next dev-mode start re-serialized identical content, saw different text and reported a change. That marks package.json as modified and runs a full package install on the first reload of a fresh project, while the user waits. Compare the parsed content instead, so the same configuration in a different layout is not a change.
-
Make configuration init parameters unmodifiable
Commit · Pull requestConfiguration properties should not accept changes after generation. Now any tries to change property value is met with an exception. Closes #9299
-
Keep the development frontend token out of production archives
Commit · Pull request · IssuevaadinPrepareFrontend writes a development flow-build-info.json into resourceOutputDirectory, and the plugin registered that folder as a resources source folder unconditionally. Invoking the task explicitly then caused two failures: - processResources consumed the folder without any ordering against the task producing it, so Gradle failed with an implicit dependency validation error. - In a production build the development token was copied into build/resources/main while vaadinBuildFrontend wrote its own token into its task-owned output directory, so the archive ended up with two conflicting copies of META-INF/VAADIN/config/flow-build-info.json and the jar/war task failed. A folder left behind by an earlier development build was enough to trigger this, without the two tasks ever sharing a task graph. Register resourceOutputDirectory as a resources source folder only in development mode - in production vaadinBuildFrontend generates the whole META-INF/VAADIN tree into its own output directory - and declare the ordering that processResources and vaadinBuildFrontend need relative to vaadinPrepareFrontend, without adding a dependency that would make the task execute on every build.
-
Resolve route scope UI from the detach event
Commit · Pull request · IssueRouteStoreWrapper#getBeanStore re-points a bean store to the UI created by a browser refresh, but the store's detach listener stays on the previous UI. resetUI() then asked findPreservingUI() about currentUI, which is no longer the UI the detach event comes from. If the refreshed UI had already been removed from the session, its session reference is null and findPreservingUI() threw a NullPointerException. The exception escaped before the branch that destroys the store, so the route scoped beans were not destroyed and the store stayed in routeStores. During session expiration the beans are still released by the session destroy listener of RouteStoreWrapper, but when only the UIs of an idle browser window are removed nothing cleans them up and they leak until the session ends. Pass the detached UI from the event into resetUI() so the lookup always gets the UI the event originates from, which still has its session at that point. findPreservingUI() now also returns null instead of dereferencing a UI that has no session anymore.
-
Shortcuts should not leak over popover or modal boundary
Commit · Pull request · IssueBlock shortcut propagation if crossing a popover-open or modal boundary. This makes dialog shortcuts not propagate up from a nested dialog.
Vaadin Flow 25.1.14
Changes since 25.1.13
Fixes
-
Collect frontend dependencies of dev tools message handlers (#25089) (CP: 25.1)
Commit · Pull requestFrontendDependencies resolves DevToolsMessageHandler subtypes to add them as internal entry points, but the class was missing from the
@HandlesTypesof DevModeStartupListener. DevModeClassFinder only knows the classes listed there and throws for anything else, and that exception was swallowed by the surrounding catch block intended for a missing dev tools classpath entry. As a result, frontend dependencies declared by dev tools plugins were silently skipped in development mode when the byte-code scanner is enabled. -
Resolve route scope UI from the detach event (#25064) (CP: 25.1)
Commit · Pull request · IssueRouteStoreWrapper#getBeanStore re-points a bean store to the UI created by a browser refresh, but the store's detach listener stays on the previous UI. resetUI() then asked findPreservingUI() about currentUI, which is no longer the UI the detach event comes from. If the refreshed UI had already been removed from the session, its session reference is null and findPreservingUI() threw a NullPointerException. The exception escaped before the branch that destroys the store, so the route scoped beans were not destroyed and the store stayed in routeStores. During session expiration the beans are still released by the session destroy listener of RouteStoreWrapper, but when only the UIs of an idle browser window are removed nothing cleans them up and they leak until the session ends. Pass the detached UI from the event into resetUI() so the lookup always gets the UI the event originates from, which still has its session at that point. findPreservingUI() now also returns null instead of dereferencing a UI that has no session anymore.
Vaadin Flow 24.10.10
Changes since 24.10.9
Fixes
-
Collect frontend dependencies of dev tools message handlers (CP: 24.10)
Commit · Pull requestFrontendDependencies resolves DevToolsMessageHandler subtypes to add them as internal entry points, but the class was missing from the
@HandlesTypesof DevModeStartupListener. DevModeClassFinder only knows the classes listed there and throws for anything else, and that exception was swallowed by the surrounding catch block intended for a missing dev tools classpath entry. As a result, frontend dependencies declared by dev tools plugins were silently skipped in development mode when the byte-code scanner is enabled. -
Resolve route scope UI from the detach event (CP: 24.10)
Commit · Pull request · IssueRouteStoreWrapper#getBeanStore re-points a bean store to the UI created by a browser refresh, but the store's detach listener stays on the previous UI. resetUI() then asked findPreservingUI() about currentUI, which is no longer the UI the detach event comes from. If the refreshed UI had already been removed from the session, its session reference is null and findPreservingUI() threw a NullPointerException. The exception escaped before the branch that destroys the store, so the route scoped beans were not destroyed and the store stayed in routeStores. During session expiration the beans are still released by the session destroy listener of RouteStoreWrapper, but when only the UIs of an idle browser window are removed nothing cleans them up and they leak until the session ends. Pass the detached UI from the event into resetUI() so the lookup always gets the UI the event originates from, which still has its session at that point. findPreservingUI() now also returns null instead of dereferencing a UI that has no session anymore.
Vaadin Flow 24.9.25
Changes since 24.9.24
Fixes
-
Collect frontend dependencies of dev tools message handlers (CP: 24.10) (#25097) (CP: 24.9)
Commit · Pull requestFrontendDependencies resolves DevToolsMessageHandler subtypes to add them as internal entry points, but the class was missing from the
@HandlesTypesof DevModeStartupListener. DevModeClassFinder only knows the classes listed there and throws for anything else, and that exception was swallowed by the surrounding catch block intended for a missing dev tools classpath entry. As a result, frontend dependencies declared by dev tools plugins were silently skipped in development mode when the byte-code scanner is enabled. -
Resolve route scope UI from the detach event (CP: 24.10) (#25069) (CP: 24.9)
Commit · Pull requestThis PR cherry-picks changes from the original PR #25064 to branch 24.10. --- #### Original PR description > RouteStoreWrapper#getBeanStore re-points a bean store to the UI created by a > browser refresh, but the store's detach listener stays on the previous UI. > resetUI() then asked findPreservingUI() about currentUI, which is no longer > the UI the detach event comes from. > > If the refreshed UI had already been removed from the session, its session > reference is null and findPreservingUI() threw a NullPointerException. The > exception escaped before the branch that destroys the store, so the route > scoped beans were not destroyed and the store stayed in routeStores. During > session expiration the beans are still released by the session destroy > listener of RouteStoreWrapper, but when only the UIs of an idle browser > window are removed nothing cleans them up and they leak until the session > ends. > > Pass the detached UI from the event into resetUI() so the lookup always gets > the UI the event originates from, which still has its session at that point. > findPreservingUI() now also returns null instead of dereferencing a UI that > has no session anymore. > > Fixes #25027
Vaadin Flow 25.2.6
Changes since 25.2.5
Fixes
-
Read minimum frontend package age from config in dev mode (#25101) (CP: 25.2)
Commit · Pull requestThe dev mode initializer built the frontend Options without reading the npm.minimumFrontendPackageAgeDays property, so the minimum package age check was ignored at runtime and always fell back to the Options default of one day. The Maven build path already wired this through, making dev mode inconsistent with the build. Read the property in DevModeInitializer and pass it to the Options via withMinimumFrontendPackageAgeDays.
-
Collect frontend dependencies of dev tools message handlers (#25089) (CP: 25.2)
Commit · Pull requestFrontendDependencies resolves DevToolsMessageHandler subtypes to add them as internal entry points, but the class was missing from the
@HandlesTypesof DevModeStartupListener. DevModeClassFinder only knows the classes listed there and throws for anything else, and that exception was swallowed by the surrounding catch block intended for a missing dev tools classpath entry. As a result, frontend dependencies declared by dev tools plugins were silently skipped in development mode when the byte-code scanner is enabled. -
Do not reinstall packages when pnpm reformats its workspace file (#25084) (CP: 25.2)
Commit · Pull request · IssuePnpmWorkspaceFile.save() compared the serialized text of pnpm-workspace.yaml against the file on disk. pnpm rewrites that file while installing, in its own formatting, so the next dev-mode start re-serialized identical content, saw different text and reported a change. That marks package.json as modified and runs a full package install on the first reload of a fresh project, while the user waits. Compare the parsed content instead, so the same configuration in a different layout is not a change.
-
Keep the development frontend token out of production archives (#25071) (CP: 25.2)
Commit · Pull request · IssuevaadinPrepareFrontend writes a development flow-build-info.json into resourceOutputDirectory, and the plugin registered that folder as a resources source folder unconditionally. Invoking the task explicitly then caused two failures: - processResources consumed the folder without any ordering against the task producing it, so Gradle failed with an implicit dependency validation error. - In a production build the development token was copied into build/resources/main while vaadinBuildFrontend wrote its own token into its task-owned output directory, so the archive ended up with two conflicting copies of META-INF/VAADIN/config/flow-build-info.json and the jar/war task failed. A folder left behind by an earlier development build was enough to trigger this, without the two tasks ever sharing a task graph. Register resourceOutputDirectory as a resources source folder only in development mode - in production vaadinBuildFrontend generates the whole META-INF/VAADIN tree into its own output directory - and declare the ordering that processResources and vaadinBuildFrontend need relative to vaadinPrepareFrontend, without adding a dependency that would make the task execute on every build.
-
Shortcuts should not leak over popover or modal boundary (#25044) (CP: 25.2)
Commit · Pull request · IssueBlock shortcut propagation if crossing a popover-open or modal boundary. This makes dialog shortcuts not propagate up from a nested dialog.
-
Resolve route scope UI from the detach event (#25064) (CP: 25.2)
Commit · Pull request · IssueRouteStoreWrapper#getBeanStore re-points a bean store to the UI created by a browser refresh, but the store's detach listener stays on the previous UI. resetUI() then asked findPreservingUI() about currentUI, which is no longer the UI the detach event comes from. If the refreshed UI had already been removed from the session, its session reference is null and findPreservingUI() threw a NullPointerException. The exception escaped before the branch that destroys the store, so the route scoped beans were not destroyed and the store stayed in routeStores. During session expiration the beans are still released by the session destroy listener of RouteStoreWrapper, but when only the UIs of an idle browser window are removed nothing cleans them up and they leak until the session ends. Pass the detached UI from the event into resetUI() so the lookup always gets the UI the event originates from, which still has its session at that point. findPreservingUI() now also returns null instead of dereferencing a UI that has no session anymore.
Vaadin Flow 25.3.0-alpha6
Changes since 25.3.0-alpha5
New features
-
Compress static resources
Commit · Pull request · IssueAdd compression of static resources in META-INF/resources to Brotli and Gzip for production build.
Fixes
-
Parse SNAPSHOT versions with extra qualifier segments
Commit · Pull requestsetVersion only matched the \d+.\d+-SNAPSHOT shape, so a version with an extra qualifier such as 25.3.tsclient-SNAPSHOT produced no match and crashed on null[2], taking down the whole CI matrix computation before any job ran. Broaden the pattern to any -SNAPSHOT version and guard against a missing match so a mismatch degrades gracefully.
-
Reflect RangeInput initial value to the DOM
Commit · Pull request · IssueA RangeInput created with its default value (0.0) never rendered at 0 as setting default nothing writes the value property. Instead the slider appeared in the middle of its range — 10 for a 0–20 range etc. Explicitly set the value property in constructor.
-
Downgrade Vite to 8.0
Commit · Pull requestDowngrade Vite until rolldown/rolldown#10281 gets fixed. Related to #24982
-
Make vaadinBuildFrontend build cache relocatable
Commit · Pull request · IssueThe task cache key embedded absolute project paths, so a shared build cache never hit across checkouts at different locations. Directory inputs no longer contribute their absolute path to the key.
-
Include
/usr/binas location for linux tools
Commit · Pull requestWhen installing nodejs through the package manager it lands in
/usr/bin
Vaadin Flow 25.2.5
Changes since 25.2.4
Breaking changes
-
Restore cached Gradle frontend build outputs (#25001) (CP: 25.2)
Commit · Pull request · IssueGradle production builds could produce application archives (JAR/WAR) without the Vaadin frontend resources when the
vaadinBuildFrontendoutput was restored from Gradle's build cache, causing the packaged application to fail in production because the client bundle was missing. The production frontend output is now a declared task output, so it is correctly restored from the build cache and reliably packaged into the application archive, including custom archive tasks. The newincludeArchiveTasksandexcludeArchiveTasksoptions let you control which archives receive the frontend bundle. Breaking change: a customfrontendOutputDirectorymust now follow theMETA-INF/VAADIN/webapplayout (as the default does). A value that does not end inMETA-INF/VAADIN/webappis rejected with a build error in production mode. Previously it silently produced an archive without the frontend bundle and, on Gradle 9, failed with an implicit task-dependency error.Breaks ONLY Gradle projects defining a custom
frontendOutputDirectorynod ending inMETA-INF/VAADIN/webapp.
Fixes
-
Make vaadinBuildFrontend build cache relocatable (#25033) (CP: 25.2)
Commit · Pull request · IssueThe task cache key embedded absolute project paths, so a shared build cache never hit across checkouts at different locations. Directory inputs no longer contribute their absolute path to the key. ---------
-
Include
/usr/binas location for linux tools (#25026) (CP: 25.2)
Commit · Pull requestWhen installing nodejs through the package manager it lands in
/usr/bin -
Expose production frontend bundle on the runtime classpath (#25024) (CP: 25.2)
Commit · Pull request · IssueThe production frontend bundle produced by vaadinBuildFrontend was written to a task-owned directory (build/vaadin-build-frontend) that is not on the runtime classpath. It was copied into application archives with an explicit Jar.from(...), but never exposed on the classpath, so an application served in place from the source set output - gretty during a production build, or an IDE/bootRun launch - no longer found the bundle or the production flow-build-info.json and started in development mode, failing with "There is no dev-bundle ... found". Register the bundle directory as an extra output of the main source set (output.dir(builtBy: vaadinBuildFrontend)), restoring the behavior that shipped through 25.1.x: the bundle is on the runtime classpath for in-place runs and is packaged into every application archive through standard source-set-output handling (WEB-INF/classes for WAR, the archive root for plain and Spring Boot executable jars). The task-owned output directory introduced in #25001 is kept, so the build-cache fix (#24012) is preserved. Because output.dir makes the
classeslifecycle task depend on vaadinBuildFrontend, this task no longer depends onclasses(which would form a cycle). Ordering after compilation is established by its@ClasspathclassesDirs input, and ordering after resource processing by an explicit dependency on the processResources task. The per-archive Jar.from(...) copying, the Spring Boot BOOT-INF/classes special-casing, and the includeArchiveTasks/excludeArchiveTasks options (all introduced in 25.3.0-alpha4, never in a stable release) are no longer needed and are removed. The Spring Boot bundle location returns to the archive root, matching 25.1.x. -
Write pnpm overrides to pnpm-workspace.yaml (#24918) (CP: 25.2)
Commit · Pull requestRecent pnpm versions no longer read the "pnpm" field from package.json, so the dependency overrides Flow generated there were silently ignored and pnpm logged a warning about it. As a result Flow could no longer lock transitive dependencies to the platform versions when using pnpm. Flow now writes these overrides to pnpm-workspace.yaml, the location pnpm actually reads, and moves any overrides left in package.json over to it. Existing user content in pnpm-workspace.yaml is preserved, and a Flow-generated file is cleaned up like other generated frontend files.
-
Respect custom npm registry in seeded package-lock.json (#24921) (CP: 25.2)
Commit · Pull requestWhen seeding a project's
package-lock.jsonfrom the dev-bundle template, Flow copied it verbatim, keeping the hardcodedregistry.npmjs.orgURLs in everyresolvedfield. With a custom npm registry configured, this leaves a committed lock (withcleanFrontendFiles=false) that still points atregistry.npmjs.org, and packages can end up being downloaded from npmjs instead of the configured registry — for example when only a scoped@scope:registryis set, or when npm's registry-host rewriting is turned off. This breaks private/air-gapped setups and any tooling that consumes the lock without npm's rewriting. Strip theresolvedfields from the seeded npmpackage-lock.jsonwhen a custom registry is configured, so npm re-resolves the download URLs against that registry. Theintegrityhashes are kept so npm still verifies the downloaded tarballs against the versions Vaadin tested. Default setups keep the verbatim fast-path copy. Whether a custom registry is configured is now determined by npm itself (npm config ls --json) rather than by scanning.npmrcfiles, so it also covers registries set through environment variables, the global npmrc, or the command line, as well as scoped registries. -
Prevent NPE in ElementEffect detach listener on re-attach (#25005) (CP: 25.2)
Commit · Pull request · IssueElementEffect registered a new detach listener on every attach, stored it in the single detachRegistration field, and relied on each detach listener removing itself. When an element is re-attached without a detach event firing in between - StateNode.removeFromTree(false), as used by UIInternals.moveToNewUI for
@PreserveOnRefresh- a second detach listener was registered while the first was still present. The next real detach ran both: the first nulled detachRegistration, the second dereferenced null and threw a NullPointerException. Register the detach listener through a helper that removes any previous registration before adding a new one, and null-guard the removal inside the listener so at most one detach listener is ever active. -
Skip vaadinBuildFrontend in development mode (#25002) (CP: 25.2)
Commit · Pull request · IssueThe Gradle vaadinBuildFrontend task is now skipped when Vaadin production mode is not enabled. This prevents development and multi-module builds from failing when the task is part of the build graph, and avoids producing a production configuration while running in development mode.
Vaadin Flow 25.1.13
Changes since 25.1.12
Fixes
-
Include
/usr/binas location for linux tools (#25026) (CP: 25.1)
Commit · Pull requestWhen installing nodejs through the package manager it lands in
/usr/bin -
Respect custom npm registry in seeded package-lock.json (#24921) (CP: 25.1)
Commit · Pull requestWhen seeding a project's
package-lock.jsonfrom the dev-bundle template, Flow copied it verbatim, keeping the hardcodedregistry.npmjs.orgURLs in everyresolvedfield. With a custom npm registry configured, this leaves a committed lock (withcleanFrontendFiles=false) that still points atregistry.npmjs.org, and packages can end up being downloaded from npmjs instead of the configured registry — for example when only a scoped@scope:registryis set, or when npm's registry-host rewriting is turned off. This breaks private/air-gapped setups and any tooling that consumes the lock without npm's rewriting. Strip theresolvedfields from the seeded npmpackage-lock.jsonwhen a custom registry is configured, so npm re-resolves the download URLs against that registry. Theintegrityhashes are kept so npm still verifies the downloaded tarballs against the versions Vaadin tested. Default setups keep the verbatim fast-path copy. Whether a custom registry is configured is now determined by npm itself (npm config ls --json) rather than by scanning.npmrcfiles, so it also covers registries set through environment variables, the global npmrc, or the command line, as well as scoped registries. -
Prevent NPE in ElementEffect detach listener on re-attach (#25005) (CP: 25.1)
Commit · Pull request · IssueElementEffect registered a new detach listener on every attach, stored it in the single detachRegistration field, and relied on each detach listener removing itself. When an element is re-attached without a detach event firing in between - StateNode.removeFromTree(false), as used by UIInternals.moveToNewUI for
@PreserveOnRefresh- a second detach listener was registered while the first was still present. The next real detach ran both: the first nulled detachRegistration, the second dereferenced null and threw a NullPointerException. Register the detach listener through a helper that removes any previous registration before adding a new one, and null-guard the removal inside the listener so at most one detach listener is ever active.
Vaadin Flow 25.3.0-alpha5
Changes since 25.3.0-alpha4
Fixes
-
Expose production frontend bundle on the runtime classpath
Commit · Pull request · IssueThe production frontend bundle produced by vaadinBuildFrontend was written to a task-owned directory (build/vaadin-build-frontend) that is not on the runtime classpath. It was copied into application archives with an explicit Jar.from(...), but never exposed on the classpath, so an application served in place from the source set output - gretty during a production build, or an IDE/bootRun launch - no longer found the bundle or the production flow-build-info.json and started in development mode, failing with "There is no dev-bundle ... found". Register the bundle directory as an extra output of the main source set (output.dir(builtBy: vaadinBuildFrontend)), restoring the behavior that shipped through 25.1.x: the bundle is on the runtime classpath for in-place runs and is packaged into every application archive through standard source-set-output handling (WEB-INF/classes for WAR, the archive root for plain and Spring Boot executable jars). The task-owned output directory introduced in #25001 is kept, so the build-cache fix (#24012) is preserved. Because output.dir makes the
classeslifecycle task depend on vaadinBuildFrontend, this task no longer depends onclasses(which would form a cycle). Ordering after compilation is established by its@ClasspathclassesDirs input, and ordering after resource processing by an explicit dependency on the processResources task. The per-archive Jar.from(...) copying, the Spring Boot BOOT-INF/classes special-casing, and the includeArchiveTasks/excludeArchiveTasks options (all introduced in 25.3.0-alpha4, never in a stable release) are no longer needed and are removed. The Spring Boot bundle location returns to the archive root, matching 25.1.x. -
Write pnpm overrides to pnpm-workspace.yaml
Commit · Pull requestRecent pnpm versions no longer read the "pnpm" field from package.json, so the dependency overrides Flow generated there were silently ignored and pnpm logged a warning about it. As a result Flow could no longer lock transitive dependencies to the platform versions when using pnpm. Flow now writes these overrides to pnpm-workspace.yaml, the location pnpm actually reads, and moves any overrides left in package.json over to it. Existing user content in pnpm-workspace.yaml is preserved, and a Flow-generated file is cleaned up like other generated frontend files.
Vaadin Flow 25.3.0-alpha4
Changes since 25.3.0-alpha3
Breaking changes
-
Restore cached Gradle frontend build outputs
Commit · Pull request · IssueGradle production builds could produce application archives (JAR/WAR) without the Vaadin frontend resources when the
vaadinBuildFrontendoutput was restored from Gradle's build cache, causing the packaged application to fail in production because the client bundle was missing. The production frontend output is now a declared task output, so it is correctly restored from the build cache and reliably packaged into the application archive, including custom archive tasks. The newincludeArchiveTasksandexcludeArchiveTasksoptions let you control which archives receive the frontend bundle. Breaking change: a customfrontendOutputDirectorymust now follow theMETA-INF/VAADIN/webapplayout (as the default does). A value that does not end inMETA-INF/VAADIN/webappis rejected with a build error in production mode. Previously it silently produced an archive without the frontend bundle and, on Gradle 9, failed with an implicit task-dependency error.
New features
-
Reject uploads with a synchronous validator
Commit · Pull request · IssueThe pre-made upload handlers offered no supported way to refuse an upload while it was being received; only a fully custom
UploadHandlercould callUploadEvent.reject(...). Subclassing a pre-made handler to reject a captured event did not help: rejection was signalled asynchronously and never checked, so the success callback still ran and file handlers left the written file on disk. AddUploadValidator, registered viawithValidator(...), which is invoked synchronously while the upload is received and can callUploadEvent.reject(...)to abort it before it is stored. Downloads are unaffected.
Fixes
-
Respect custom npm registry in seeded package-lock.json
Commit · Pull requestWhen seeding a project's
package-lock.jsonfrom the dev-bundle template, Flow copied it verbatim, keeping the hardcodedregistry.npmjs.orgURLs in everyresolvedfield. With a custom npm registry configured, this leaves a committed lock (withcleanFrontendFiles=false) that still points atregistry.npmjs.org, and packages can end up being downloaded from npmjs instead of the configured registry — for example when only a scoped@scope:registryis set, or when npm's registry-host rewriting is turned off. This breaks private/air-gapped setups and any tooling that consumes the lock without npm's rewriting. Strip theresolvedfields from the seeded npmpackage-lock.jsonwhen a custom registry is configured, so npm re-resolves the download URLs against that registry. Theintegrityhashes are kept so npm still verifies the downloaded tarballs against the versions Vaadin tested. Default setups keep the verbatim fast-path copy. Whether a custom registry is configured is now determined by npm itself (npm config ls --json) rather than by scanning.npmrcfiles, so it also covers registries set through environment variables, the global npmrc, or the command line, as well as scoped registries. -
Prevent NPE in ElementEffect detach listener on re-attach
Commit · Pull request · IssueElementEffect registered a new detach listener on every attach, stored it in the single detachRegistration field, and relied on each detach listener removing itself. When an element is re-attached without a detach event firing in between - StateNode.removeFromTree(false), as used by UIInternals.moveToNewUI for
@PreserveOnRefresh- a second detach listener was registered while the first was still present. The next real detach ran both: the first nulled detachRegistration, the second dereferenced null and threw a NullPointerException. Register the detach listener through a helper that removes any previous registration before adding a new one, and null-guard the removal inside the listener so at most one detach listener is ever active. -
Skip vaadinBuildFrontend in development mode
Commit · Pull request · IssueThe Gradle vaadinBuildFrontend task is now skipped when Vaadin production mode is not enabled. This prevents development and multi-module builds from failing when the task is part of the build graph, and avoids producing a production configuration while running in development mode.