Production ready Gradle Vaadin Flow applications
If we all would only need to support the latest version of Google Chrome then this article would most likely not need to exist. However, in real life we certainly will want to support other browsers as well so lets have a look how we can take our Vaadin Flow application built with Gradle and make it production ready.
Supporting old browsers
At this stage I could go into a lengthy rant about the difference between Ecmascript 5 and Ecmascript 6, different transpilers and linters, polyfills and polygons, how the world is an unfair place and how the frontend technologies are moving way to fast for any company to ever be able to support them.
But instead I will just say that most of the Web Components today only target the most bleeding edge browsers because developers only like to tinker with new things, so we need to compile the javascript source code into different versions which different browsers can load.
The Gradle plugin added support for this via the vaadin.productionMode
property in the 1.0.0.M2 release.
Production mode
When the application is set to production mode it signals the plugin that it will need to compile two versions of the frontend, one for old browsers and one for new browsers.
To do that the first thing the plugin will do is unpack any webjars you have included via Gradle. That includes the Vaadin dependencies as well as any custom Webjar you have added.
Note: Here it is important to mention that any WebJar you add need to have the Javascript sources included in the jar as well as a bower.json file. If they are missing then the WebJar will be excluded from compilation.
Once the Webjars have been unpacked the plugin performs the compilations and copies over the two new versions of the frontend into the src/main/webapp
folder. These folders are frontend-es5
and frontend-es6
. It will also copy anything you had in src/main/webapp/frontend
(for example your theme) into those directories.
Note: You should not modify these directories as they are just a compilation result. Anything you change in them will be overwritten in the next compilation.
Note: You might want to exclude
src/main/webapp/frontend-es5
andsrc/main/webapp/frontend-es5
from version control (add them to .gitignore) as they are compilation results.
Enabling production mode in the Vaadin application
While turning on vaadin.productionMode
will make the Gradle plugin know you want to deploy to production but the Vaadin app will still be running in development mode.
The first thing you have to know is that when Vaadin is running in development mode it is expecting everything to be located under src/main/webapp/frontend
. This is ok as it allows you to develop faster without compiling.
To make the Vaadin application also run in production mode we need to set the productionMode
init-parameter. We can do that by setting it on the servlet like so:
@WebServlet(urlPatterns = "/*", name = "TestServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = TestUI.class, productionMode = true)
public class TestServlet extends VaadinServlet { }
What this will do is tell Vaadin to instead use src/main/webapp/frontend-es5
for older browsers and src/main/webapp/frontend-es6
for newer browsers.
Another thing you also will need to do is to use the generated index.html
file in the frontend directories. To do that add @HtmlImport("index.html")
to your UI class like so:
import com.vaadin.flow.component.dependency.HtmlImport;
import com.vaadin.flow.component.UI;
@HtmlImport("index.html")
public class MyUI extends UI { }
The plugin will add the import automatically to new projects you create with vaadinCreateProject
but for older projects you might need to add it manually.
Development with production mode configured
Once you have turned on production mode your build will start to take longer due to the compilation.
A good tip to mitigate this is to use a Gradle parameter or system property for productionMode so you can only have it on in your CI builds and otherwise have it off while developing.
To do that we first have to configure our build.gradle to use the parameter, to do that add the following:
vaadin.productionMode = findProperty('productionMode') ?: false
Next, we will need to add a placeholder for the property in our Servlet class as well. Change the @VaadinServletConfiguration
to look like this:
@VaadinServletConfiguration(ui = TestUI.class, productionMode = @PRODUCTION_MODE@ )
Finally, add the following task to your build.gradle:
// Pre-process Java sources
sourceSets.main.java.srcDirs = ['build/processedSrc']
task processSources(type: Copy) {
from 'src/main/java'
into 'build/processedSrc'
filter { line -> line.replaceAll('@PRODUCTION_MODE@', "$vaadin.productionMode") }
}
compileJava.dependsOn processSources
After you have done that you can now control the prodution mode switch from the command line by appending the -PproductionMode=true
parameter. For example like so:
$ gradle -PproductionMode=true jettyRun
Of course, now that you have the source processing in place you could also replace the version etc. with the same functionality ;)