Babel: Runtime, Polyfill … was wann?

the next big thing  –  0 Kommentare

Wer in JavaScript entwickelt, kommt kaum an Babel vorbei: Der Transpiler übersetzt zeitgemäßen JavaScript-Code in solchen, der auch in älteren Webbrowsern lauffähig ist. Dabei stößt man immer wieder auf einige auf den ersten Blick verwirrende Module wie @babel/polyfill und @babel/runtime. Wofür und vor allem wann braucht man sie?

Der Einsatz von Babel könnte so einfach sein, wären da nicht eine Reihe von Modulen, deren Zweck sich nicht unbedingt auf den ersten Blick erschließt und bei denen vor allem häufig nicht klar ist, welches Modul wann aus welchen Gründen gebraucht wird:

Dabei haben alle drei Module im Grunde das gleiche Ziel: Während Babel an sich lediglich die Sprachkonstrukte aus modernem JavaScript zurückübersetzt, stellen die Module ein ES2015-Ökosystem zur Verfügung. Das bedeutet, dass sie dafür zuständig sind, Klassen wie Promise für alte Webbrowser zu implementieren.

Am einfachsten ist das mit @babel/polyfill nachvollziehbar: Das Modul verändert den globalen Scope, sodass die ES2015-APIs anschließend jeglichem geladenen JavaScript-Code zur Verfügung stehen. Weil das Modul den globalen Scope verändert, soll und darf es auch nur ein einziges Mal geladen werden. Die Verwendung dieses Moduls ist also vor allem auf Applikationsebene sinnvoll.

Dem gegenüber steht das Modul @babel/runtime, das prinzipiell das Gleiche macht – aber nicht den globalen Scope verändert, sondern als reguläre Abhängigkeit geladen werden kann und daher eine bessere Kompatibilität mit Drittmodulen bietet. Allerdings fügt es bestehenden Klassen keine Instanzmethoden hinzu – denn dazu müsste deren Prototyp verändert werden, was wiederum nur im globalen Scope möglich ist.

Schlussendlich existiert auch noch @babel/plugin-transform-runtime, das den Code zwar so verändert, dass die Funktionen des Runtime-Moduls genutzt werden können, dessen Code aber nicht in jede Datei direkt einbindet. Das verkleinert die Dateigröße, weil diverse Runtime-Funktionen auf dem Weg wiederverwendet werden können und deshalb nur ein einziges Mal geladen werden müssen.

Das liefert nun auch die Erklärung, welches Modul wann zu verwenden ist: Entwickelt man eine Anwendung und ist es in Ordnung, den globalen Scope zu verändern, bietet @babel/polyfill die beste Kompatibilität. Schreibt man hingegen ein Modul, sollte man auf @babel/runtime zurückgreifen, gegebenenfalls in Verbindung mit @babel/plugin-transform-runtime.

tl;dr: Wer mit Babel eine ES2015-Umgebung simulieren will, braucht entweder @babel/polyfill oder @babel/runtime. Der Polyfill eignet sich für Anwendungen, die Runtime hingegen für Module. Um zu verhindern, dass Code aus der Runtime in jede Datei eingebunden wird, lässt sich das mit @babel/plugin-transform-runtime optimieren.