Aufgaben eines Bundlers
Ein Hauptaufgabe eines Bundlers besteht in der Analyse und Umwandlung von Eingabedateien in ein oder mehrere Zieldateien. An der Oberfläche erinnert dies zunächst an einen Compiler, wobei Bundler jedoch intrinsisch keinerlei Kenntnis der Dateiinhalte sammeln oder benötigen. Stattdessen benutzen Bundler u. a. Compiler (oder Transpiler) um die Arbeit zu verrichten.
So können Bundler über alle tatsächlich verwendeten JavaScript Module iterieren. Bei der anschließenden Analyse werden Optimierungen und Umwandlungen durchgeführt, so dass am Ende Code rauskommt, der auf allen gewünschten Zielplattformen möglichst optimiert ausgeführt werden kann.

Neben JavaScript können auch nahe Verwandte wie bspw. TypeScript, CoffeeScript, etc. als Eingabedaten verwendet werden. Auch andere Formate wie Bilder, StyleSheets, oder HTML Dateien sind bei vielen Bundlern integrierbar.
Vorhandene Lösungen
Die wohl populärste Lösung heißt „Webpack“ (https://webpack.js.org). Hierbei handelt es sich um einen modularen Bundler, der ohne Zusatzmodule quasi uneinsetzbar ist. Webpack benötigt zur Ausführung auf jeden Fall eine Konfigurationsdatei, da die Erweiterungsmodule ansonsten nicht gefunden bzw. eingesetzt werden können.
Eine weitere Lösung gibt es mit „Rollup“ (https://rollupjs.org). Das Alleinstellungsmerkmal ist die exzellente Umsetzung von sog. Treeshaking, so dass wirklich nur der verwendete Code in den Ausgabedateien enthalten ist. Als Nachteil von Rollup ist die wesentlich kleinere Community und die noch stärkere Modularisierung hervorzuheben. Beispielsweise verweigert Rollup den Dienst bei Eingabedateien im CommonJS Format – es sei denn, ein entsprechendes Plugin wird verwendet.
Als Gegenvorschlag zur extremen Modularisierung von Rollup dient „Parcel“ (https://parceljs.org). Parcel versteht sich als konfigurationsloser Bundler, der ohne Installation von Erweiterungen und ohne eine spezielle Konfigurationsdatei loslegen kann. Der Nachteil: Parcel kommt bereits zur Installation mit jeder Menge Abhängigkeiten bzw. Module.
Neben den drei Platzhirschen gibt es noch jede Menge weiterer Alternativen: Mit Browserify und Brunch sind zwei etablierte Systeme am Start. Fuse bringt TypeScript in die erste Liga. Mit Packem existiert auch ein nativer Bundler, der nicht in JavaScript, sondern in Rust geschrieben wurde.

Ein kleiner Vergleich
Nimmt man als Startpunkt ein kleines Projekt, das unter Zuhilfenahme eines Bundlers für den produktiven Einsatz umgewandelt werden soll, so erhält man schnell eine Aussage über die Qualität der vorhandenen Lösungen.
In unserem Fall handelte es sich bei dem Projekt um eine einfache Webseite, die React mit TypeScript und Sass einsetzt. Die genauen Details sind im GitHub Repository (https://github.com/FlorianRappl/bundler-comparison) zu finden.
Die folgende Tabelle fasst das Ergebnis für die drei bekanntesten Bundler zusammen.
Webpack | Parcel | Rollup | |
Veröffentlichungsjahr | 2011 | 2017 | 2014 |
Aktuelle Version | 4.41.3 | 1.12.4 | 1.27.13 |
GitHub Stars | 52.300 | 34.100 | 17.200 |
CLI Tooling | Getrennt | Ja | Ja |
Pakete notwendig | 9 | 1 | 8 |
Pakete installiert | 457 | 743 | 229 |
Konfigurationsgröße [LoC] | 40 | 0 | 50 |
JS Ausgabe in [kB] | 130 | 132 | 132 |
Geschwindigkeit / 1. Lauf [s] | 5 | 7 | 7 |
Geschwindigkeit / Cache [s] | 4 | 2 | 2 |
Anzahl notwendige Änderungen | 2 | 0 | 3 |
Schwierigkeitsgrad | Durchschnitt | Einfach | Schwierig |
Flexibilität | Hoch | Mittel | Mittel |
Am Ende gibt es keinen eindeutigen Gewinner. Je nachdem, was einem wichtig ist, sollte die Auswahl getroffen werden. Wichtig ist hierbei, dass bei größeren Projekten immer das gesamte Team involviert wird.
Fazit
Während man bei Webpack aufgrund der Community Situation sicherlich nie verkehrt liegt, ist Parcel aufgrund der Einfachheit sicherlich ein perfekter Startkandidat. Rollup wird v. a. durch bereits vorkonfigurierte Abstraktionen wie bspw. Microbundle (https://github.com/developit/microbundle) interessant.
Mehr dazu in einer der nächsten Ausgaben der „web und mobile“.