Vaadin 14 Plugins - under the hood
Neither the Vaadin Gradle Plugin nor the Vaadin Maven Plugin really document what they’re doing under the hood. When something goes wrong, it’s very hard for a server-side guy like myself to know what’s going on, especially since the entire JavaScript client-side landscape is pretty much a mystery to a Java guy. Hence this blog post.
Both Maven and Gradle Vaadin Plugins do pretty much the same thing; they both have two goals/tasks:
vaadin:prepare-frontend
for Maven,vaadinPrepareFrontend
for Gradlevaadin:build-frontend
for Maven,vaadinBuildFrontend
for Gradle
Note: If you feel lost at any point, please read the Vaadin: the missing guide article first.
Important: that this article discusses the npm mode only: since the compatibility/bower mode is deprecated, we’re not going to discuss that anymore.
prepare-frontend
The prepare-frontend goal/task does the following things (you can follow the text below and look into the sources of the Vaadin Gradle Plugin prepare-frontend task implementation if you’d like):
First, the plugin will prepare the very important flow-build-info.json
file into
the classpath, into the target/
or build/
folder (depends on whether you use Maven or Gradle).
By placing it into the target/
folder, the file will then later on be packaged
correctly into the target artifact, be it WAR, EAR or SpringBoot jar. This way
it is also visible to Vaadin when launching Vaadin with embedded Jetty.
Important: Since the
flow-build-info.json
file is removed when running theclean
task, it’s really good to remember to run theprepare-frontend
task after theclean
task.
The next step is for the Vaadin Plugin to validate that the npm and node.js is of acceptable
version, and will warn or fail if either one is too old. If either of the npm or node.js is missing,
Vaadin plugin will automatically download both, into the $HOME/.vaadin/node
folder.
Afterwards, Vaadin plugin will generate the necessary npm and webpack configuration files:
webpack.config.js
, webpack.generated.js
and package.json
. Note that the
node_modules
nor package-lock
files are not generated at this point:
they will be generated later on:
- In development mode: Vaadin Servlet will run npm and webpack automatically, before the app is started, to populate those folders.
- In production mode, you run
build-frontend
which will run npm and webpack and will produce the huge JavaScript file, containing all npm modules.
After the prepare-frontend
finishes, you’re all set to run the Vaadin application
in the development mode.
build-frontend
build-frontend
builds on the outcome of the prepare-frontend
task, and thus
it requires the prepare-frontend
task to be run beforehand.
Note: The Gradle Vaadin Plugin configures Gradle to handle this automatically, so if you run
vaadinBuildFrontend
task, thevaadinPrepareFrontend
task is going to be run, too.
You can again follow the Vaadin Gradle plugin build-frontend task implementation.
First, the flow-build-info.json
file is modified. Since we are targeting production mode here,
the Vaadin Servlet will no longer start embedded webpack and will serve precompiled
JavaScript files instead. That’s why we set enableDevServer
to false and remove
all npm-related settings like npmFolder
, generatedFolder
and frontendFolder
.
We can also remove pnpm.enable
since it doesn’t matter how the precompiled JavaScript
files were produced. Also we remove require.home.node
since in production mode
we do not need node.js
, npm
nor webpack
anymore, since the precompiled JavaScript
files will be produced by the Plugin and packaged into the WAR/EAR/JAR archive.
Next, we will run npm install
to make sure all packages are available in node_modules
,
in order for webpack to be able to produce the precompiled JavaScript files (the runNodeUpdater()
function
in plugin’s sources).
Lastly, webpack
is run, to package everything from frontend/
and node_modules
into
the precompiled JavaScript files bundle.
If this task succeeds, it should produce the following outputs:
node_modules
andpackage-lock
in the project root folder;- The
META-INF/VAADIN/config/flow-build-info.json
file into the folder where generated resources go; - The
META-INF/VAADIN/config/stats.json
into the folder where generated resources go; - The
META-INF/VAADIN/build/
folder hosting generated JavaScript bundle, into the folder where generated resources go.
The placement of generated resources depends on whether the project is built by
Maven (then the folder is somewhere in target/classes/
) or Gradle (then it’s in build/resources/main/
).
It is now the job of the packaging plugin (WAR/EAR/JAR) to package those files
and folders properly, so that Vaadin can use ClassLoader to load those files as
resources from the classpath. For example:
- When building JAR without Spring Boot (see vaadin14-embedded-jetty example project), those folders are simply located in the root of the jar file;
- When building WAR (see e.g. skeleton-starter)
then the folders are located in
WEB-INF/classes/
; - When building JAR+Spring Boot (e.g. skeleton-starter-flow-spring, those folders are located in
BOOT-INF/classes/
in the Spring Boot jar file.
Please see Vaadin: the missing guide on the example contents of those files and folders.
What to read next
See the Vaadin: Troubleshooting guide when something goes wrong.