Differential Serving

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Es gibt "futuristisches" JavaScript, das wir schreiben können. "Stage 0" bezieht sich auf Ideen für die JavaScript-Sprache, die noch Vorschläge sind. Dennoch könnte jemand diese Idee in ein Babel-Plugin umwandeln und es könnte in Code kompiliert werden, der an jeden Browser ausgeliefert werden kann. Für einige dieser glücklichen Vorschläge wird Stage 0 zu 1, 2, 3 und schließlich zu einem offiziellen Teil der Sprache.

Es gab eine Zeit, in der selbst die grundlegenden Funktionen von ES6 eher experimentell waren. Man würde keine Pfeilfunktion in die Produktion ausliefern – man würde sie zu ES5 kompilieren und diese stattdessen ausliefern. Aber ES6 (aka ES2015, vor vier Jahren!) ist nicht mehr experimentell. Seine Funktionen sind keine Vorschläge, Entwürfe oder Kandidaten. Sie sind fertige Teile der Sprache mit breiter Unterstützung.

Die größten Hürden bei der Browserunterstützung sind IE <= 11 und Safari <= 9. Es ist durchaus möglich, dass Sie diese Browser nicht unterstützen. In diesem Fall können Sie ES6-Funktionen frei in die Produktion ausliefern, und das sollten Sie wahrscheinlich auch tun, da Ihr Code kleiner und effizienter sein wird, als wenn Sie ihn zu ES5 kompilieren würden. Philip hat einige Tests durchgeführt und seine Ergebnisse deuten darauf hin, dass sowohl Dateigrößen als auch Parse-/Eval-Zeiten halbiert oder besser sein können, indem die neuen Funktionen übernommen werden. Wenn Sie jedoch Browser unterstützen müssen, die keine Unterstützung bieten, müssen Sie zu ES5 kompilieren, aber das bedeutet nicht, dass Sie ES5 an alle Browser ausliefern müssen. Darum geht es bei "Differential Serving".

Wie setzt man das um? Ein Weg, der verlockend clever ist, ist dieses Muster, das ich zuerst von Philip Walton schreiben sah

<!-- Browsers with ES module support load this file. -->
<script type="module" src="main.mjs"></script>

<!-- Older browsers load this file (and module-supporting -->
<!-- browsers know *not* to load this file). -->
<script nomodule src="main.es5.js"></script>

Lassen Sie sich von diesem .mjs-Zeug nicht verwirren; es ist nur eine erfundene Dateierweiterung, die bedeutet: "Dies ist eine JavaScript-Datei, die das importieren von ES6-Modulen unterstützt" und sie ist völlig optional. Ich würde sie wahrscheinlich nicht einmal verwenden.

Das Konzept ist aber großartig. Wir müssen keine ausgefallenen JavaScript-Feature-Tests schreiben und dann selbst eine Netzwerkanfrage für das richtige Bundle auslösen. Wir können diese Aufteilung direkt auf HTML-Ebene vornehmen. Ich habe sogar kleine Bibliotheken gesehen, die dies nutzen, um sich selbst zu beschränken, speziell auf moderne Browser.

John Stewart hat dies kürzlich getestet, um zu sehen, ob es die Aufgabe erfüllt, die wir ihm zuschreiben, und, falls ja, ob es sie gut erfüllt. Zuerst beschreibt er, wie man die beiden Bundles tatsächlich erstellt, was einige Webpack-Konfigurationen erfordert. Dann testete er, ob es tatsächlich funktionierte.

Die gute Nachricht ist, dass die meisten Browser – insbesondere neuere – mit Differential Serving perfekt zurechtkommen. Aber es gibt einige, die das nicht tun. Safari 10 (2016) ist ein besonders schlechter Übeltäter, da es beide Versionen herunterlädt und ausführt. Firefox 59 (2018) und IE 11 laden beide herunter (führen aber die richtige aus), und Edge 18 lädt irgendwie beide Versionen herunter und dann die Module-Version *nochmal*. Alles Browser, die ziemlich schnell verschwinden, aber nicht zu ignorieren sind. Es lohnt sich trotzdem? Wahrscheinlich. Ich wäre daran interessiert, alternative Techniken zu untersuchen, die gegen diese Fallstricke vorgehen.