Webjars

Frontend-Abhängigkeiten bequem mit Maven verwalten

Im Java-Umfeld gehören Dependency-Management-Tools wie Maven, Gradle oder SBT einfach zum guten Ton — trotzdem enden deren Zuständigkeiten meist im Backend. Für das Frontend wird entweder kein Dependency-Management verwendet (großer Fehler) oder auf separate Tools wie bower, npm oder yarn gesetzt.

Wenn man stattdessen alle Abhängigkeiten bequem über Maven verwalten möchte, lohnt sich ein Blick auf Webjars.

Webjars sind client-seitige Dependencies, die in JARs verpackt wurden. Durch einbinden der JARs liegen Ressourcen für den Client auf dem Classpath und können einfach referenziert werden, ohne ein aufwändigeres Verpackungs-Script oder eine gesonderte Build-Pipeline zu bauen. Webjars können einfach über MavenCentral bezogen werden.

Webjars lassen sich mit beliebiger JVM-Technologie verheiraten. In diesem Artikel zeige ich, wie Webjars in Spring Boot + Spring MVC und in Java EE verwendet werden. Das Ziel für beide Demos ist, eine Bootstrap-Hinweisbox darzustellen, die per Mausklick geschlossen werden kann.

Für unsere Bootstrap-Demo benötigten wir nur eine einzige Dependency: das Bootstrap-Webjar. Folgender Codeschnipsel in der pom.xml fügt es zum Projekt hinzu:

<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.1.0</version>
</dependency>

Dass diese Dependency die korrekten Webjars herunterlädt, können wir über die IDE oder Maven verifizieren: Man kann erkennen, dass Bootstrap mit den transitiven Abhängigkeiten für jQuery und popper.js (beide ebenfalls als Webjar verfügbar) heruntergeladen wird.

Dependency-Tree des Bootstrap-Webjars

Nun fehlt nur noch ein minimaler Controller und ein Thymeleaf-View. Der Controller macht nichts anderes als den Pfad zur View zurückzugeben. Die View zeigt unsere Bootstrap-Hinweis-Box an, die durch einen Klick ausgeblendet werden kann. Hier der Hinweis ohne Webjar:

Hinweisbox ohne Bootstrap-Style

Damit die Hinweis-Box korrekt dargestellt wird und der Schließen-Button funktioniert, binden wir schließlich unser Webjar innerhalb des <head>-Tags ein:

<link rel=”stylesheet” href=”/webjars/bootstrap/4.1.0/css/bootstrap.min.css”>
<script src=”/webjars/jquery/3.0.0/jquery.min.js”></script>
<script src=”/webjars/popper.js/1.14.1/popper.min.js”></script>
<script src=”/webjars/bootstrap/4.1.0/js/bootstrap.min.js”></script>

Das Ergebnis:

fertig gestylter Hinweis

In Spring gibt es zusätzlich die Möglichkeit, auf die Versionen in den Inklusionen zu verzichten. Das hat den Vorteil, dass bei Änderungen an der Version in der pom.xml am Markup nichts geändert werden muss:

<link rel=”stylesheet” href=”/webjars/bootstrap/css/bootstrap.min.css”>

In welchem Versionsordner sich welche Abhängigkeit befindet, wird automatisch aufgelöst. Folgende zusätzliche Maven-Dependency ist dafür notwendig:

<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.30</version>
</dependency>

Um das initiale Feature-Set der Webjars-Einbindung in Java EE zu erreichen, reicht es auch hier das jeweilige webjar per Maven-Dependency einzubinden, um anschließend in der Lage zu sein, eine Dependency zu referenzieren.

Je nach Application-Servern können zusätzliche Dependencies notwendig sein. JBoss AS und Wildfly benötigen z.B. noch webjars-locator-jboss-vfs, damit der Locator mit Wildflys virtuellem Dateisystem zurechtkommt.

Leider ist es nicht so leicht wie bei Spring Boot möglich, bei der Referenzierung auf die Versionsnummern zu verzichten. Da ich das bei Spring Boot allerdings so angenehm fand, wollte ich nichts unversucht lassen, einen ähnlichen Komfort in Java EE zu genießen. Hierfür habe ich einen kleinen Webfilter geschrieben, der dass Auflösen der Versionsnummern übernimmt. Den Filter (WebJarFilter.java) findet ihr im Github-Repository am Ende des Artikels.

Dieser Artikel hat am Beispiel von Spring Boot und Java EE gezeigt, wie man client-seitige Libraries mit Maven verwalten und einbinden kann. Wie das mit anderen Framworks, wie z.B. dem Play Framework oder Apache Wicket funktioniert, ist in der Webjars-Doku beschrieben.

Bei Webjars handelt es sich keineswegs um eine neue Technologie, die ursprüngliche Implementierung stammt aus dem Jahr 2015. Dennoch stellen Webjars eine angenehme Art und Weise dar, client-seitige Dependencies zu verwalten und einzubinden.

Das vollständige Code-Beispiele findet ihr in folgendem Repository:

Den Webfilter gibt es zusätzlich als separates Github-Repository, welches auf Maven-Central veröffentlicht wurde, damit es einfacher in ein eigenes Projekt eingebunden werden kann. Auch das ist im vollständigen Code-Beispiel enthalten.