In den letzten 15 Jahren hat sich das JavaScript-Ökosystem rasant erweitert und unzählige Tools eingeführt, die die Entwicklung erleichtern. Doch diese Tools haben ihren Preis: wachsende Paketgrößen. Tatsächlich zeigen Daten aus dem HTTP-Archiv, dass die durchschnittliche Menge an pro Seite übertragenem JavaScript von 90 KB im Jahr 2010 auf 650 KB im Jahr 2024 gestiegen ist (Quelle).
Trotz zunehmender Akzeptanz und Fortschritten bei der Komprimierung zeigt dieser Trend keine Anzeichen einer Verlangsamung. Während wir weiterhin Funktionen hinzufügen, bleibt die Herausforderung bestehen: Wie können wir weniger JavaScript versenden?
Seltsamerweise sind die Lösungen sowohl einfach als auch schwierig. Der einfache Teil sind die Optimierungen auf Projektebene, die zu schnellen Erfolgen führen können. Der schwierige Teil besteht darin, eine dauerhafte Wirkung zu erzielen, was eine gemeinschaftsweite Änderung zur Verbesserung von Bundlern, Bibliotheken und Tools erfordert.
Dieser Artikel konzentriert sich auf umsetzbare Verbesserungen für Ihre Projekte und behandelt Folgendes:
Zukünftige Artikel werden sich mit ökosystemweiten Verbesserungen befassen, die wir vornehmen können, aber zunächst wollen wir uns damit befassen, wie diese Faktoren zu aufgeblähten Paketen beitragen – und wie man damit umgeht.
JavaScript ist die Engine hinter der modernen Web-Interaktivität, aber es ist nicht kostenlos. JavaScript ist die rechenintensivste Ressource, die Ihr Browser verarbeiten muss. Oftmals ist es der Engpass, der darüber entscheidet, ob sich eine Seite schnell oder träge anfühlt, da ein aufgeblähtes Paket das Rendern blockieren und die Gesamtleistung beeinträchtigen kann.
Je größer das JavaScript-Bundle ist, desto länger dauert das Laden, Parsen, Kompilieren und Ausführen. Dies verzögert alles andere – etwa die Anzeige von Inhalten oder die Interaktion der Benutzer mit der Seite. Für jemanden, der einen High-End-Laptop mit Glasfaseranschluss hat, könnte das ein kleines Ärgernis sein. Aber für jemanden mit einem Telefon mit geringer Leistung oder einem lückenhaften Netzwerk kann es den Unterschied zwischen dem Verbleib oder dem vollständigen Verlassen Ihrer Website ausmachen.
Der erste Schritt zur Reduzierung der JavaScript-Bundle-Größe ist Tree Shaking (oder „Eliminierung toten Codes“), was die meisten Bundler sofort durchführen. Aber sind alle Bundler gleich?
Bündelung in JavaScript hat einen langen Weg zurückgelegt – von manueller Verkettung und Task-Runnern bis hin zu ausgefeilten Bundlern. Heutzutage steht die Bundler-Leistung im Mittelpunkt, wobei Entwickler schnellere Builds priorisieren. Allerdings Build-Geschwindigkeit ist nicht alles. Ebenso wichtig ist die Größe der von ihnen produzierten Bundles, da kleinere Bundles zu schnelleren Ladezeiten für Benutzer führen.
Auf der Suche nach einer besseren Leistung sind wir vom Schreiben von Bundlern in JavaScript zu Sprachen wie Rust und Go übergegangen. Für diesen Wechsel war es erforderlich, sie von Grund auf neu zu schreiben, sodass alle Funktionen und Optimierungen, die in den alten Bundlern vorhanden waren, neu implementiert werden müssen. Auf lange Sicht wird sich dies wahrscheinlich auszahlen. Kurzfristig bedeutet dies jedoch, dass ihnen einige Funktionen fehlen, die JavaScript-Bundler jahrelang entwickelt haben, wie etwa das gute Tree Shaking. Und genau diese Funktion kann uns helfen, die Paketgröße zu minimieren.
Natürlich ist Reden billig, also schauen wir uns die Zahlen an, ja?
Vergleichen wir acht beliebte Bibliotheken und bündeln sie mit sieben beliebten Bundlern. Der Fairness halber habe ich Folgendes verwendet:
Die genauen Konfigurationen finden Sie im Benchmark-Setup-Repository.
Getestete Bundler:
Beachten Sie, dass sich Rolldown zum Zeitpunkt des Verfassens dieses Artikels noch in der Alpha-Phase befindet, also im Nachteil ist und seine Ergebnisse sich mit der Zeit wahrscheinlich verbessern werden.
Getestete Bibliotheken:
Diese Bibliotheken variieren in Größe und Funktionen – einige können fast wie eigenständige Anwendungen funktionieren.
Beginnen wir mit der Build-Geschwindigkeit, da dies etwas ist, das den Entwicklern offenbar sehr am Herzen liegt. Wenn alle diese Bibliotheken gebündelt werden, ist esbuild mit einer Build-Zeit von 192 ms der Gewinner. Im Vergleich zur langsamsten Aufbauzeit von 7,23 Sekunden ist das über 37-mal schneller.
Basierend auf diesen Ergebnissen können wir die Bundler in drei Kategorien einteilen:
Die Unterschiede sind eklatant. Rolldown und Rspack sind beispielsweise 11,5-mal bzw. 3,3-mal schneller als ihre älteren Gegenstücke Rollup und Webpack – und das alles unter Beibehaltung der theoretischen Abwärtskompatibilität. Der Wechsel zu diesen neueren Bundlern könnte die Produktivität bei größeren Projekten erheblich steigern.
Wenn es um die Ausgabegröße geht, sind die Unterschiede nicht so drastisch wie die Bauzeiten, aber sie sind dennoch wichtig.
Bei der Bündelung aller acht Bibliotheken ist Vite mit einer Ausgabegröße von 2087 KiB der Gewinner. Im Vergleich zur größten Ausgabegröße von 2576 KiB ist das eine über 23,5 % kleinere Ausgabe.
Ein 23,5 % Unterschied in der Ausgabegröße ist erheblich: Bei einer langsamen 3G-Verbindung kann das Herunterladen des kleinsten Pakets etwa 5,7 Sekunden dauern, während das größte eher bei 7 Sekunden liegt. Die Parsing- und Ausführungszeiten skalieren auch mit der Bundle-Größe, sodass der Unterschied in der Praxis noch deutlicher ausfallen könnte.
Basierend auf diesen Ergebnissen können wir die Bundler-Ausgaben erneut in drei Kategorien einteilen:
Aggregierte Ergebnisse geben kein vollständiges Bild wieder, da es unwahrscheinlich ist, dass Sie alle oben aufgeführten Bibliotheken in Ihrem Projekt verwenden werden. Interessanter ist, wie diese Bundler mit den einzelnen Bibliotheken umgehen.
Bei Bibliotheken wie chart.js und mobx kann die Wahl des Bundlers die Ausgabegröße dramatisch beeinflussen, wobei die Unterschiede bis zu 70 % betragen. Dies unterstreicht, wie wichtig es ist, Bundler mit Ihren spezifischen Abhängigkeiten zu testen. In den meisten anderen Fällen ist der Unterschied viel geringer und liegt bei etwa 20–30 %.
Außerdem landete Webpack zwar insgesamt im Mittelfeld, schnitt aber in 6 von 8 Fällen am besten ab. Da es jedoch bei der Bündelung von handsontable und chart.js eine viel schlechtere Leistung erbrachte, landete es dort, wo es war. Dies bedeutet, dass Webpack je nach den von Ihnen verwendeten Bibliotheken eine gute Wahl sein kann.
Auf der anderen Seite des Spektrums haben wir Rolldown. In 7 von 8 Fällen schnitt es am schlechtesten ab (denken Sie daran, dass es sich noch in der Alpha-Phase befindet).
Rspack ist eine ähnliche Geschichte. Obwohl es eine bessere Leistung als Rolldown erbrachte, produzierte es dennoch ein viel größeres Bundle als die anderen Bundler.
Wenn Sie erwägen, auf einen neueren Bundler zu migrieren, testen Sie ihn mit den von Ihnen verwendeten Bibliotheken, um zu sehen, ob die schnellere Build-Geschwindigkeit nicht auf Kosten einer größeren Ausgabegröße geht.
Wie gezeigt, sind neuere Bundler viel schneller, produzieren aber möglicherweise größere Bundles. Vergleichen Sie bei der Migration von einem älteren Bundler nicht nur die Erstellungszeiten, sondern auch die resultierenden Bundle-Größen. Möglicherweise tauschen Sie schnellere Builds gegen größere Pakete ein.
Nachdem Angular beispielsweise von Webpack auf Esbuild umgestiegen war, berichteten einige Entwickler, dass die Größe einer leeren Angular-App um etwa 20 KB zunahm. Dies unterstreicht perfekt den Kompromiss zwischen Build-Geschwindigkeit und Bundle-Größe.
Das heißt nicht, dass Sie nicht auf die Build-Geschwindigkeit achten sollten, denn sie ist wichtig für die Produktivität und Zufriedenheit der Entwickler. Es gibt auch einen Zusammenhang zwischen der CI-Erstellungszeit und der Zeit, die zum Zusammenführen des Codes benötigt wird.
Achten Sie bei der Auswahl eines Bundlers zunächst auf die Funktionen, die er bietet. Streben Sie dann ein Gleichgewicht zwischen Build-Geschwindigkeit und Bundle-Größe an. Wählen Sie den Bündler aus, der in der für Sie angenehmen Zeit möglichst das kleinste Bündel produzieren kann.
Testen Sie einige repräsentative Bibliotheken aus Ihrem Projekt. Wenn Ihre Abhängigkeiten den größten Teil Ihrer Codebasis ausmachen, können die Unterschiede, die Sie in diesen Benchmarks sehen, ein guter Indikator für Ihre Situation sein.
Als nächstes auf unserer Liste stehen externe Bibliotheken, die oft den Großteil Ihres JavaScript-Pakets ausmachen. In vielen, wenn nicht den meisten Anwendungen, an denen ich gearbeitet habe, machten sie den Großteil der Paketgröße aus. Deshalb ist es so wichtig, sie mit Bedacht auszuwählen (und zu nutzen).
Viele von uns haben Bibliotheken wie lodash, axios oder moment installiert, nur um eine einzelne Funktion zu nutzen – was zu aufgeblähten Anwendungen führt. Diese Bibliotheken sind großartig und historisch bedeutsam, aber als sie immer beliebter wurden, wurden einfachere Alternativen geschaffen und einige ihrer Funktionen wurden der Sprache selbst hinzugefügt.
Das können wir ausnutzen. Ich könnte native APIs oder neuere und kleinere Alternativen für diese Bibliotheken auflisten, aber es gibt bereits viele Artikel dazu. Und es gibt so viele andere Bibliotheken, dass es unmöglich wäre, sie alle abzudecken.
Deshalb gebe ich Ihnen nur einen allgemeinen Rat, einen Blick auf die von Ihnen verwendeten Bibliotheken zu werfen und zu prüfen, ob Sie diese entfernen oder durch native APIs oder kleinere Alternativen ersetzen können. Die YOU MIGHT NOT NEED *-Website ist eine großartige Ressource für den Anfang.
Die meisten Bibliotheken sind standardmäßig nicht auf ihre Größe optimiert, einige bieten jedoch spezielle Installationspfade oder Teil-Builds an. Selbst unter den Bibliotheken in unserem Test bieten chart.js, handsontable und ckeditor5 eine Möglichkeit, die Größe der Bibliothek zu reduzieren, indem sie nur die Teile einschließen, die Sie benötigen. Schauen wir uns als Beispiel ckeditor5 an.
Der Standardinstallationspfad führt zu einer Bundle-Größe zwischen 660 und 800 KiB. Wenn wir jedoch den optimierten Installationspfad verwenden, sinkt die Bundle-Größe auf 603–653 KiB, wobei nur das von Rolldown erstellte Bundle etwa 750 KiB groß ist. Dies entspricht je nach Bundler einer Größenreduzierung von 7 bis 23 %.
Eine weitere Sache, auf die Sie achten sollten, sind doppelte Abhängigkeiten. Dies ist ein überraschend häufiges Problem bei JavaScript-Anwendungen. Beispielsweise verfügte das Bluesky-Einbettungs-Widget über zwei Versionen der Zod-Validierungsbibliothek. Durch das Entfernen des Duplikats wurde die Paketgröße um ca. 9 % reduziert.
Dieses Problem tritt normalerweise nicht auf, weil Sie zwei verschiedene Versionen derselben Bibliothek abgerufen haben, sondern weil Sie und eine der externen Bibliotheken von derselben Bibliothek abhängig sind, jedoch in unterschiedlichen Versionen. Dies kann häufig durch die Aktualisierung der Bibliotheken, auf die Sie angewiesen sind, gelöst werden.
Vor diesem Hintergrund können wir uns endlich dem letzten Puzzleteil zuwenden – Ihrem Projekt. Hier erfahren Sie, was Sie tun können, um Ihre Pakete zu verkleinern und die Leistung zu verbessern.
Der erste Schritt ist Sichtbarkeit. Ohne zu verstehen, was sich in Ihren Paketen befindet, wird das Verkleinern ihrer Größe zu einem Ratespiel. Hierfür können Sie einen von mir erstellten Bundle-Analysator und Visualisierer namens Sonda verwenden. Es funktioniert mit den meisten oben genannten Bundlern (außer Parcel) und zeigt genau die Größe der einzelnen Dateien an, die zum Bundle beitragen.
Sie können damit beginnen, es in Ihrem Projekt zu installieren und Teile Ihres Bundles visuell zu überprüfen.
Sobald Sie den Inhalt der Pakete gut verstanden und die Teile identifiziert haben, die optimiert werden können, können Sie auf die Diagrammkacheln klicken, um Folgendes anzuzeigen:
Sonda warnt Sie auch vor doppelten Abhängigkeiten, sodass Sie die Ursache des Problems schnell identifizieren und beheben können.
Idealerweise sollten Sie nicht nur eine einmalige Inspektion durchführen, sondern eine kontinuierliche Überwachung als Teil Ihrer CI-Pipeline einrichten. Das Verfolgen von Änderungen im Laufe der Zeit, insbesondere bei großen Projekten, kann Ihnen dabei helfen, zu verhindern, dass sich kleine Änderungen im Laufe der Zeit zu einer erheblichen Aufblähung entwickeln.
Der schnellste Code ist der Code, den Sie nicht versenden. Wann immer möglich:
Wenn Sie einen Teil Ihrer Anwendung nicht entfernen können, versuchen Sie es mit der Codeaufteilung. Durch die Codeaufteilung können Sie das Laden bestimmter Teile Ihrer App verschieben, bis sie benötigt werden, und so die anfänglichen Ladezeiten verkürzen.
Verwenden Sie Dynamic Import(), um Module bei Bedarf zu laden. Wenn beispielsweise eine bestimmte Funktion erst benötigt wird, wenn der Benutzer auf eine Schaltfläche klickt, verschieben Sie das Laden bis zu diesem Zeitpunkt.
Moderne Frontend-Frameworks unterstützen Lazy Loading out of the box und machen es so einfacher denn je, Code-Splitting in Ihren Workflow zu integrieren.
Dies ist ein allgemeiner Rat, der jedoch eine Wiederholung wert ist. Befolgen Sie die Best Practices, wie zum Beispiel:
Wenn Sie daran interessiert sind, das Web schneller zu machen oder einfach nur neue Dinge zu lernen, sollten Sie darüber nachdenken, der Ecosystem Performance-Community beizutreten. Wir konzentrieren uns auf drei Hauptbereiche:
Ich hoffe, dieser Artikel zeigt, dass Sie dieselben Funktionen mit weniger Code bereitstellen können. Die Bundle-Größen können unkontrolliert wachsen, wenn sie nicht verwaltet werden, aber selbst kleine Änderungen können die Leistung erheblich verbessern.
Beginnen Sie noch heute: Analysieren Sie Ihre Bundles, testen Sie ein neues Tool oder ersetzen Sie eine umfangreiche Bibliothek. Die Wirkung wird Sie überraschen.
Ich hoffe, Ihnen hat dieser Artikel gefallen. Wenn Sie Fragen oder Kommentare haben oder mehr über ein bestimmtes Thema erfahren möchten, teilen Sie mir dies bitte in den Kommentaren unten mit. Wenn Sie mehr über das Thema JavaScript-Leistung, Bündelung und Tree-Shaking erfahren möchten, können Sie mir hier oder auf BlueSky folgen und der e18e-Community beitreten.
Das obige ist der detaillierte Inhalt vonVerkleinern Sie Ihr JavaScript: Beherrschen Sie Bundler-Optimierungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!