esbuild, Teil 1: JavaScript-Bundling leicht gemacht

Seite 4: esbuild – effizient, langlebig und erweiterbar

Inhaltsverzeichnis

esbuild ist nicht als Build-Tool gedacht, sondern getreu der Unix-Philosophie ein Tool für einen Zweck: das Transpilieren von JavaScript. Es ist demnach kein Ersatz für make, Grunt, Gulp und Co., sondern wird von ihnen verwendet. Der Autor verwendet übrigens weder Gulp noch eines der unzähligen anderen JavaScript-spezifischen Build-Tools, sondern make. make bietet den Vorteil, dass man – wenn man einmal damit warm geworden ist – sein Wissen darüber jahrzehntelang pflegen und perfektionieren kann. Entwicklerinnen und Entwickler, die bisher auf Gulp, Grunt und Co. gesetzt haben, sollten sich make unbedingt anschauen. Es befreit nicht nur davon, alle fünf Jahre das nächstbeste Build-Tool erlernen zu müssen, sondern arbeitet zudem enorm effizient.

In den derzeit gehypten Bundlern Vite.js und Snowpack übernimmt esbuild die Rolle eines JavaScript-Transpilers, der von Haus aus JSX, TypeScript und selbst brandneue JavaScript-Sprachfeatures wie den Optional Chaining Operator und Nullish Coalescing Operator unterstützt. Der Einsatz von esbuild bietet einen großen Geschwindigkeitsvorteil gegenüber anderen Bundlern und Transpilern, wie die nachfolgende Grafik zeigt:

esbuild schneidet im Performance-Vergleich mit anderen Bundlern wie webpack deutlich besser ab.

(Bild: esbuild)

Neben der stark erhöhten Performance hat esbuild weitere Vorteile.

Die esbuild-Macher haben viel von den Problemen der webpack- und Babel-Transpilerentwicklung gelernt. So entschieden sie sich dafür, den JavaScript-Parser komplett in Go zu entwickeln, anstatt wie bei Babel auf in JavaScript geschriebene Parser-Erweiterungen für alle neuen Features zu setzen. In Go geschriebene Programme werden in nativen Maschinencode kompiliert, was die enorme Performance von esbuild gegenüber webpack und Co. erklärt. Da esbuild bereits alle JavaScript-Features in Go implementiert, entfällt die Konfiguration eines Plug-ins für jedes kleine Feature, wie es in webpack nötig wäre.

Nicht zuletzt bringt der monolithische (Go-)Ansatz einen weiteren Vorteil: Er ist einfach zu nutzen. Da im Monolith alles Nötige eingebacken ist, was zur JavaScript-Transpilation nur denkbar wäre, sind für die Transpilation keine zusätzlichen Erweiterungen zu installieren und konfigurieren.

Wer schon einmal Babel konfigurieren musste, weiß das monolithische Konzept von esbuild zu schätzen. "Welches Babel-Plug-in muss ich noch installieren, damit dieses oder jenes JavaScript-Feature unterstützt wird?" – esbuild-Nutzern ist dieses Problem fremd. "Monolithisch" ist heutzutage immer ein wenig negativ behaftet, doch unter Bereitstellung durchdacht designter und damit langfristig stabiler Schnittstellen ist der Ansatz im konkreten Anwendungsfall eher ein Vorteil.

Zur Erweiterbarkeit bringt esbuild eine Plug-in-Schnittstelle mit, über die sich sowohl mittels Go als auch JavaScript individuelle Funktionen hinzufügen lassen. Mittlerweile existieren dafür viele Plug-ins, die auf der esbuild-Homepage gelistet werden. Diese API werden wir uns im zweiten Teil der Artikelserie zunutze machen.

esbuild bietet für die Konfiguration der API verschiedene Möglichkeiten: die Kommandozeilen-Schnittstelle, die JavaScript- und die Go-API. Die erste Option entfällt für unsere Zwecke, da sie die Verwendung von Plug-ins (noch) nicht unterstützt. Die alternative JavaScript-Schnittstelle ist Nutzerinnen und Nutzern von Gulp, Grunt oder webpack nicht unbekannt. Dort kommt ebenfalls die JavaScript-API zur Anwendung. "Configuration as Code" ist an der Stelle ohnehin wesentlich praktikabler als eine hypothetische Kommandozeile, die unleserlich lang werden würde.

Die Verwendung existierender esbuild-Plug-ins kann oft mehr Probleme nach sich ziehen als das Plug-in löst. Zur Veranschaulichung eignet sich die Sass-Integration (Syntactically Awesome Stylesheets).

Für esbuild gibt es aktuell zwei Plug-ins, die Sass-CSS-imports implementieren. Man hat also die Qual der Wahl, welches Plug-in wohl das passende ist.

Bei genauerer Betrachtung fällt auf, dass in beiden Plug-ins das Durchreichen der Sass-Optionen entweder gar nicht oder nur teilweise umgesetzt ist. Außerdem neigen manche Plug-in-Autoren bei der Benennung von Plug-in-Optionen zu mehr Kreativität als notwendig, anstatt einfach die Parameter des durch das Plug-in gewrappten Tools eins zu eins an das Tool durchzureichen. Das erschwert die Nutzung dieser Plug-ins erheblich, da Anwender erst bei Sass nachschauen müssen, wie das Sass-Feature heißt, und dann in der Dokumentation des Plug-ins nachlesen müssen, wie der Autor den Parameter im Plug-in genannt hat.

Zum anderen, und das ist der gewichtigere Punkt, haben Entwicklerinnen und Entwickler keinen Einfluss mehr auf die Version des Sass-Compilers, da er als Dependency des Plug-ins enthalten ist. Im schlimmsten Fall entfällt daher die Chance, eine neuere Version des eigentlichen Tools – in diesem Fall des Sass-Compilers – zu verwenden. Stattdessen bleibt nur die Hoffnung, dass der Plug-in-Autor zeitnah eine neue Version des Plug-ins veröffentlicht.

Gerade in Bezug auf die Integration existierender Tools wie Sass ist es vorteilhafter, das selbst in der Hand zu haben.