I am trying to migrate a working vaadin 13 web application to vaadin 14 and I can’t quite seem to get it correct. Our application does do some custom theme work which is causing some of the problems and I am also trying to figure out how to properly generate the frontend bundle for a production jar. In our build we use an embedded tomcat server launched from IDEA that points to our Vaadin 14 web application war file, built by a gradle build system. Simply updating our dependencies to Vaadin 14 and launching I saw an error suggesting the node application be installed.
- Failed to determine ‘node’ tool.
Ideally I would like to use the gradle node plugin which can automatically install this for our development teams but for now I simply installed NPM manually. This allow the ‘dev-mode’ logic in the vaadin-server to auto-generate the frontend bundle and allow the application to start. From the start I noticed a layout issue on our login page (see screenshot comparison). The background and layout of the text fields has changed.
After investigating I see that we use some custom css as applied to two classes in our application.
@HtmlImport("frontend://styles/shared-styles.html")
@StyleSheet("styles/shared-styles.css")
@Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes")
@Theme(value = Lumo.class)
public class WebUI_UI extends UI {...
and
@HtmlImport("frontend://styles/shared-styles.html")
@Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes")
@Theme(value = Lumo.class)
@Push
public class MainWebLayout extends VerticalLayout
implements RouterLayout, PageConfigurator, BeforeEnterObserver { ...
Where the shared-styles.css and shared-styles.html are in src/main/webapps/frontend/styles. After reading the migration guide for themes (https://vaadin.com/docs/v14/flow/theme/migrate-p2-to-p3.html) I tried to convert the items in shared-styles.html from
<dom-module id="my-grid-styles" theme-for="vaadin-grid">
<template>
<style>
[part~="body-cell"]
{
font-size: 12px;
}
</style>
</template>
</dom-module>
to a my-grid-styles.css file in src/main/webapp/frontend/styles
[part~="body-cell"]
{
font-size: 12px;
}
Then applying the annotation @CssImport(value = “styles/my-grid-styles.css”, themeFor = “vaadin-grid”) to the WebUI_UI class. After applying this for every dom-module in shared-styles.css and running again I do not see a difference in the login page. I also tried removing the @HtmlImport and @StyleSheet annotations and adding @ImportCss as described in the vaadin docs but this made the layout worse. Restoring just @StyleSheet put the back to where it originally was for my first Vaadin 14 test so I don’t think the @HtmlImport is having any impact on the layout but the @StyleSheet CSS is used and needed.
I looked deeper into the @CssImport annotation and based on the java doc I believe the shared-styles.css must be included in the frontend bundle. The way the web application is started does not align with how the vaadin dev-mode expects to find the project dir in the ‘user.dir’ of the running application and then find src/main/webapp/frontend/… To correct this I added these settings to the JVM.
-Dcom.vaadin.flow.server.project.basedir=PATH_TO_PROJECT
-Dvaadin.frontend.generated.folder=PATH_TO_PROJECT/build
-Dvaadin.frontend.frontend.folder=PATH_TO_PROJECT/frontend
With this change my css files must be be processed now because I ran into this node related error.
- ERROR dev-webpack - FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
To fix this I added the following to my environment so node will have more memory.
- NODE_OPTIONS=–max-old-space-size=8192
With this change the node error is gone but now I see this error from the webapp which I believe is the result of node not creating the ‘stats.json’ file.
- com.vaadin.flow.server.BootstrapException: Unable to read webpack stats file.
I believe the root of the problems is getting the frontend bundle to be generated correctly but I am finding this is very challenging to get correct. Is there a tool other than the maven plugin that helps with this? I tried the gradle-vaadin-flow gradle plugin but I could not get it to generate the bundle into my war file. The docs indicate to set the ‘productionMode’ flag then use the ‘war’ task, but this task did not work until I added the gradle ‘war’ plugin and then the war did not have the frontend bundle in it.
I looked at the source of the vaadin maven plugin and the vaadin ‘dev-mode’ logic, and there is a class in vaadin flow-server.jar NodeTasks.builder that I could call from gradle. Is this how the frontend bundle should be built if not using ‘dev-mode’ or the maven plugin?
Once the bundle is created correctly are there any files that should be versioned in source control because they may need to be manually edited as the project grows (webpack.config.js, package.json, …)?