Vaadin 10 is based on standalone Web Components for the client-side implementations of all components. Along with this comes a new distribution format: WebJars. Using WebJars is only recommended in cases where there is already a Bower package available. In particular, you should put your own internal Web Component implementations in src/main/webapp/frontend/
or src/main/resources/META-INF/resources/frontend/
instead of trying to create any custom WebJars-like packages.
The rest of this post is an in-depth explanation for those who want to understand the low-level details. Everyone else should just read the introduction paragraph one more time and then make sure they don't forget my advice.
Bower is a package manager for frontend dependencies
...oh you're still here? Well, let's start from the beginning then. To understand how WebJars work and why you should do as I said in the introduction, you need to be familiar with three other technologies: web fragments, Bower, and Flow's magical frontend directory. I've already covered web fragments and the frontend directory in my previous post on the topic.
You can think of Bower as the <dependencies>
part of Maven, but for frontend hippies. Since they are hippies, they use JSON instead of an enterprise-ready XML format for their dependencies, but otherwise the idea is the same.
The special thing with Bower is that packages are not published to any special repository similar to Maven Central, but instead everything is pulled straight from GitHub. Bower can also get packages from other sources, but that's irrelevant when discussing WebJars. A Bower dependency such as vaadin/vaadin-themable-mixin#^1.1.0
means that Bower will load all files from the v1.1.0
tag in the GitHub repository at https://github.com/vaadin/vaadin-themable-mixin, except files that are defined in the ignore section of the bower.json file in that repository. To publish a new version of a Bower package, all you need to do is to create a git tag and push it to GitHub.
The second thing that you need to know about Bower is that when a client-side project uses Bower, each package is downloaded into a separate directory inside the bower_components/
directory in the root of that project. Each transitive dependency is also put in its own directory in bower_components/
. In this way, a package can import files from a dependency package by using a relative path. As an example, bower_components/vaadin-grid/vaadin-grid.html
can import ../polymer/polymer-element.html
which resolves to the file bower_components/polymer/polymer-element.html
.
A WebJar is a Bower module repackaged as a web fragment
WebJars are web fragments with contents from a Bower package in META-INF/resources/webjars/<bower package name>/
. When the Flow servlet gets a request for e.g. frontend/bower_components/vaadin-grid/vaadin-grid.html
and that file isn't available as a regular static file, it also tries to find the requested file from a corresponding WebJars location and returns that file if available. Correspondly when the Maven plugin looks for files to minify, transpile and bundle for production use, it also includes files from WebJars.
Just putting the contents of a GitHub repository inside a .jar
file is by itself nothing special. The real magic is that the WebJar is also a Maven module that is deployed to Maven Central and has dependencies to WebJar representations of all dependencies from the Bower package. This means that if you add the vaadin-grid
WebJar as a dependency in an empty pom.xml
, your classpath will also contain WebJars for everything that the vaadin-grid
Bower package depends on, e.g. vaadin-lumo-styles
.
Using an existing Bower component
If you want to use a Web Component that is already available as a Bower package through GitHub, chances are that you don't need to do almost anything. You should visit https://www.webjars.org/ and search for a package with the Bower GitHub
type. In most cases, it already exists and you can directly copy a dependency snippet to add to your pom.xml
.
If it doesn't already exist, or if only an old version is available, you can deploy your own by clicking the Add a WebJar
button, selecting Bower GitHub
as the type, entering the URL of the GitHub repository and selecting a version number. Within a couple of minutes, the new WebJar with all transitive dependencies will be created and ready for use in your application or add-on.
In your Flow code, you can use files from the WebJar just as though they would be part of your own application, e.g. @HtmlImport("bower_components/paper-slider/paper-slider.html")
.
Creating your own publicly reusable Web Component
If you want to create reusable Web Component and also use it with Vaadin Flow, you should first create the Web Component and publish it as a Bower package by pushing a tag to GitHub. After that, you can follow the instructions for an already existing Bower component. src/main/resources/META-INF/resources/frontend/bower_components/
inside your add-on project since Flow will use files from that location before looking for contents from a WebJar. The
Add-on Component
starter on
https://vaadin.com/start also includes special configuration in its
pom.xml
that lets you use a shorter directory path.
Creating your own internal Web Component
At last, we come to the case that I warned against in the introduction: you have your own Web Component that you don't want to make publicly available on GitHub, but you still want to use it in your Flow project. It might be tempting to imitate the case with a publicly available Web Component by somehow creating a corresponding WebJar.
While nothing will be broken if you managed to create your own .jar file that replicates the contents of a proper WebJar, you have still caused yourself quite much trouble for very little benefits. Your WebJar imitation will not be conveniently deployed to Maven Central, it will not automatically get the right dependencies to other WebJars and other WebJars will not automatically use it as a dependency based on their own Bower dependencies.
Instead, you should treat the Web Component in the same way as the application's template files that would be based on PolymerTemplate
in Flow. This means that you put the Web Component implementation in src/main/webapp/frontend/
in the actual application or src/main/resources/META-INF/resources/frontend/
for a reusable internal library. You just need to remember to also manually add WebJars dependencies to any used frontend libraries such as Polymer to your pom.xml
.