Components not being rendered in Production Mode
In this Forum Post
I mentioned that adding <optimizeBundle>false</optimizeBundle> helped solve that problem.
This is the output log with <optimizeBundle>true</optimizeBundle> and production-profile, providing this for investigative purposes.
Vaadin Version: 24.6.6
Java version: 23.0.1
Apache Maven 3.9.8
I have removed some parts of this log( Non - Specific to Vaadin) . Hope this helps.
We have seen a similar issue several times, so probably there is a pattern in applications that we are not aware of and that causes issues like that. We have to try reproduce it by getting UI components from Spring Context as beans. Looks an impactful topic that we should improve.
I tried to reproduce in several ways but with no success. Unfortunately, also the logs do not help that much since most of the application-specific entries have been removed or redacted.
Minimal reproducible example
import java.util.function.Supplier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.checkbox.CheckboxGroup;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
@Route
public class MainView extends Div {
@Autowired
Supplier<Settings> settings;
MainView() {
var container = new Div();
add(new Button("show", e -> {
container.removeAll();
container.add(settings.get());
}));
add(container);
}
@Component
static class SettingsSupplier implements Supplier<Settings> {
@Override
public Settings get() {
return new Settings();
}
}
static class Settings extends VerticalLayout {
public Settings() {
add(new CheckboxGroup<>("settings", "a", "b", "c"));
}
}
}
Steps to reproduce
- create a project at https://start.vaadin.com/app
- select Vaadin 24.7 (latest stable)
- Java 17 or 21
- select
Pure Java with Vaadin Flowonly - download and extract the starter
- replace the main view with the example code above
- build for production:
mvn clean install -Pproduction
Important: If you modify the code during testing, be sure to clean frontend artifacts.
rm -rf node_modules package.json package-lock.json vite.generated.ts vite.config.ts src/main/frontend/generated
Observed Behavior
- the production build completes without errors
- inspecting
src/main/frontend/generated/flow/generated-flow-imports.jsshows thatvaadin-checkbox-groupimport are missing. - when running the app and clicking the "show" button, the checkbox group fails to render properly.
The browser shows elements missing their shadow DOM.
vaadin-buttoncorrectly has a#shadow-rootnodevaadin-checkbox-groupandvaadin-vertical-layoutdo not have shadow roots
Console errors are also visible:
2025-05-16T10:32:42.951+02:00 ERROR 41334 --- [nio-8080-exec-5] c.v.flow.component.internal.UIInternals : The component class com.vaadin.flow.component.checkbox.CheckboxGroup includes '@vaadin/checkbox-group/src/vaadin-checkbox-group.js' but this file was not included when creating the production bundle. The component will not work properly. Check that you have a reference to the component and that you are not using it only through reflection. If needed add a @Uses(CheckboxGroup.class) where it is used.
2025-05-16T10:32:42.952+02:00 ERROR 41334 --- [nio-8080-exec-5] c.v.flow.component.internal.UIInternals : The component class *.base.ui.view.MainView$Settings includes '@vaadin/vertical-layout/src/vaadin-vertical-layout.js' but this file was not included when creating the production bundle. The component will not work properly. Check that you have a reference to the component and that you are not using it only through reflection. If needed add a @Uses(Settings.class) where it is used.
Root cause analysis
The issue appears to be in how the flow-maven-plugin detects frontend dependencies.
- the plugin scans bytecode for direct instantiations of Vaadin components.
- it follows reference chains from entry points (like @Route classes)
- In this example, components created indirectly through the Autowired Supplier pattern are not detected
The frontend scanner (FrontendClassVisitor) successfully detects direct component creation but seem to fail to recognize components created through dependency injection.
Workaround
@Route
@Uses(CheckboxGroup.class)
@Uses(VerticalLayout.class)
public class MainView extends Div {
// ...
}
Suggested fix
Enhance the bytecode scanning to detect components created through common dependency injection and factory patterns, particularly when following chains through:
- Spring beans
- Java functional interfaces (Supplier, Function, etc.)
- Factory methods
This would improve developer experience by making component detection more robust without requiring manual @Uses annotations.
@muhammetaltindal Thanks for your comment!
As you reported, with your example code it is expected that the components are not found by the production build because the Settings class is not reachable by the bytecode scanner, since it is not directly referenced in the MainView code.
You are injecting it as a Supplier<Settings>, but due to type erasure, the scanner will only see the Supplier class.
In such situation @Uses is currently required.
BTW, @Uses(Settings.class) shoud be enough to fix the issue