Creating a production build
By default, Hilla applications are configured to run in development mode. This requires a bit more memory and CPU power, but enables easier debugging. When deploying your application to your users, you should create a production build instead.
Production configuration
The pom.xml
file in a Hilla project has the following built-in Maven configuration to create a production build:
<profiles>
<profile>
<id>production</id>
<properties>
<vaadin.productionMode>true</vaadin.productionMode>
</properties>
<!--
.. configuration depending on environment ..
-->
<executions>
<execution>
<goals>
<goal>build-frontend</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<!--
.. more configuration ..
-->
</profile>
</profiles>
The actual content of the profile depends on what environment your application is running in, but all the variants do two things:
-
Set the property
vaadin.productionMode
totrue
-
Call the Maven goal
vaadin:build-frontend
. The Maven goalvaadin:prepare-frontend
is also required, but this is often already declared in the development build.
To create a production build, you can call mvn clean package -Pproduction
.
This builds a JAR
or WAR
file with all the dependencies and transpiled front-end resources, ready to be deployed.
The file is created in the target
folder after the build completes.
If you don’t have the production Maven profile in your POM
file, the easiest way to get it’s to create a project base using the CLI, and then copy the production profile from the downloaded POM
file.
Having production build as a separate Maven profile is recommended, so that you don’t get any unexpected problems due to production settings during development.
Note
|
Building for 64-bit
If your operating system is 64-bit, make sure to use a 64-bit JDK installation as well.
|
Excluding the development server module
The webpack
server integration and live-reload features, which are available only during development, are contained in the module com.vaadin:vaadin-dev-server
.
It’s recommended to exclude this module from production builds.
You can do that by adding the following dependency exclusion to the <dependencies>
section in the production
profile:
<profiles>
<profile>
<id>production</id>
<!-- above production build configuration -->
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin</artifactId>
<exclusions>
<exclusion>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-dev-server</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</profile>
</profiles>
This results in less code and fewer dependency libraries being bundled in the production application.
Transpilation and bundling
Transpilation in Hilla means converting all ES6 JavaScript to ES5 JavaScript format for older browsers. All Vaadin components are written using ES6, and consist of several JavaScript and CSS files. Transpilation makes sure this newer JavaScript code also works in browsers which don’t support all the latest JavaScript features.
During the build, minimization is carried out to make the files smaller. When minifying code, it’s often obfuscated, which makes it harder to read. Hence, this isn’t done during development.
Bundling is an optimization where multiple files are merged to a single collection, so that the browser doesn’t need to request so many files from the server. This helps the application to load faster.
Maven plugin goals and goal parameters
prepare-frontend
This goal validates whether the node
and npm
tools are installed and aren’t too old (node
version 10 or later and npm
version 5.6 or later), and also installs them automatically to the .vaadin
folder in the user’s home directory if they are missing.
If they are installed globally but too old, there will be an error message suggesting that you install newer versions instead.
Node.js
is needed to run npm
to install front-end dependencies and webpack
, which bundles the front-end files served to the client.
In addition, it visits all the resources used by the application and copies them under the node_modules
folder, so that they are available when webpack
builds the frontend.
It also creates or updates the package.json
, webpack.config.json
and webpack.generated.json
files.
Goal parameters
- includes (default:
**/*.js,**/*.css
) -
Comma-separated wildcards for files and directories that should be copied. The default is only
.js
and.css
files. - npmFolder (default:
${project.basedir}
) -
The folder where the
package.json
file is located. The default is the project root folder. - webpackTemplate (default:
webpack.config.js
) -
Copy
webapp.config.js
from the specified URL if it’s missing. The default is the template provided by this plugin. Set it to an empty string to disable the feature. - webpackGeneratedTemplate (default:
webpack.generated.js
) -
Copy
webapp.config.js
from the specified URL if it’s missing. The default is the template provided by this plugin. Set it to an empty string to disable the feature. - generatedFolder (default:
${project.build.directory}/frontend/
) -
The folder where Flow will put generated files that will be used by
webpack
. - require.home.node (default:
false
) -
If set to
true
, always preferNode.js
automatically downloaded and installed into the.vaadin
directory in the user’s home directory.
build-frontend
This goal builds the front-end bundle. This is a complex process involving several steps:
-
update
package.json
with all the@NpmPackage
annotation values found in the classpath and automatically install these dependencies. -
update the JavaScript files containing code to import everything used in the application. These files are generated in the
target/frontend
folder, and are used as the entry point of the application. -
create
webpack.config.js
if it’s not found, or update it if some project parameters have changed. -
generate JavaScript bundles, chunks and transpile to ES5 using the
webpack
server. The target folder forWAR
packaging istarget/${artifactId}-${version}/build
; forJAR
packaging, it’starget/classes/META-INF/resources/build
.
Goal parameters
- npmFolder (default:
${project.basedir}
-
The folder where the
package.json
file is located. The default is the project root folder. - generatedFolder (default:
${project.build.directory}/frontend/
) -
The folder where Flow will put generated files that will be used by
webpack
. - frontendDirectory (default:
${project.basedir}/frontend
) -
The directory with the project’s front-end source files.
- generateBundle (default:
true
) -
Whether to generate a bundle from the project front-end sources.
- runNpmInstall (default:
true
) -
Whether to run
pnpm install
(ornpm install
, depending on the pnpmEnable parameter value) after updating dependencies. - generateEmbeddableWebComponents (default:
true
) -
Whether to generate embedded web components from
WebComponentExporter
inheritors. - optimizeBundle (default:
true
) -
Whether to include only front-end resources used from application entry points (the default) or to include all resources found on the class path. Should normally be left to the default, but a value of
false
can be useful for faster production builds or debugging discrepancies between development and production builds. - pnpmEnable (default:
false
) -
Whether to use the
pnpm
ornpm
tool to handle front-end resources. The default isnpm
. - useGlobalPnpm (default:
false
) -
Whether to use a globally installed
pnpm
tool instead of the default supported version ofpnpm
.
clean-frontend
This goal will clean-frontend
files that may cause inconsistencies when changing versions.
It’s suggested not to add the goal as a default to pom.xml
, but instead to use it with mvn vaadin:clean-frontend
when necessary.
Executing the clean-frontend
goal removes:
-
the package lock file
-
the generated front-end folder (by default
frontend/generated
) -
the
node_modules
folder (this might need manual deletion)
The goal also cleans all dependencies that are managed by the framework, and any dependencies that target the build folder from the package.json
file.
The clean-frontend
goal supports the same parameters as prepare-frontend
.