HTTP/2 war eines meiner Interessengebiete. Tatsächlich habe ich allein im letzten Jahr einige Artikel dazu geschrieben. In einem dieser Artikel habe ich diese ungeprüfte Behauptung aufgestellt:
Wenn der Benutzer HTTP/2 verwendet: Sie werden mehr und kleinere Assets ausliefern. Sie werden Dinge wie Image Sprites, eingebettetes CSS und Skripte sowie zusammengefügte Stylesheets und Skripte vermeiden.
Ich war nicht der Einzige, der das sagte, obwohl, fairerweise muss man sagen, Rachel qualifiziert ihre Aussage in ihrem Artikel mit Vorbehalten. Um fair zu sein, ist es theoretisch keine schlechte Beratung. Die Multiplexing-Fähigkeit von HTTP/2 gibt uns Spielraum, auf die Bündelung zu verzichten, ohne die negativen Auswirkungen von Head-of-Line Blocking zu erleiden (etwas, das wir in HTTP/1-Umgebungen schmerzlich gut kennen). Das Entwirren einiger dieser HTTP/1-spezifischen Optimierungen kann auch die Entwicklung erleichtern. In einer Zeit, in der die Webentwicklung komplizierter erscheint als je zuvor, wer würde nicht ein bisschen mehr Einfachheit schätzen?
Wie bei allem, was theoretisch einfach erscheint, kann die Umsetzung in der Praxis eine unübersichtliche Angelegenheit sein. Im Laufe der Zeit habe ich großartiges Feedback von nachdenklichen Lesern zu diesem Thema erhalten, das mich dazu veranlasst hat, meine ungeprüften Behauptungen darüber, welche Praktiken für HTTP/2-Umgebungen am sinnvollsten sind, zu überdenken.
Das Argument gegen Bündelung
Die Debatte über das Entbündeln von Assets für HTTP/2 dreht sich hauptsächlich um Caching. Die Prämisse ist, dass die Caching-Effizienz für wiederkehrende Benutzer mit vorgefüllten Caches besser ist, wenn Sie mehr (und kleinere) Assets anstelle eines riesigen Bundles ausliefern. Das leuchtet ein. Wenn sich ein kleines Asset ändert und der Cache-Eintrag dafür ungültig wird, wird es beim nächsten Besuch erneut heruntergeladen. Wenn sich jedoch nur ein winziger Teil eines Bundles ändert, muss das gesamte riesige Bundle erneut heruntergeladen werden. Nicht gerade optimal.
Warum Entbündelung suboptimal sein könnte
Es gibt Fälle, in denen das Entwirren von Bundles Sinn ergibt. Zum Beispiel fördert Code Splitting kleinere und zahlreichere Assets, die nur für bestimmte Teile einer Website/App geladen werden. Das macht absolut Sinn. Anstatt das gesamte JS-Bundle Ihrer Website im Voraus zu laden, zerlegen Sie es in kleinere Teile, die Sie bei Bedarf laden. Dies hält die Payloads einzelner Seiten gering. Es minimiert auch die Parsing-Zeit. Das ist gut, denn exzessives Parsen kann zu einer ruckeligen und unangenehmen Erfahrung führen, wenn eine Seite gerendert und interaktiv wird, aber noch nicht vollständig geladen wurde.
Aber es gibt einen Nachteil, den wir manchmal übersehen, wenn wir Assets zu fein aufteilen: Kompressionsverhältnisse. Im Allgemeinen komprimieren kleinere Assets nicht so gut wie größere. Tatsächlich vermeiden einige Serverkonfigurationen die Komprimierung, wenn einige Assets zu klein sind, da keine praktischen Gewinne erzielt werden können. Sehen wir uns an, wie gut einige beliebte JavaScript-Bibliotheken komprimieren
| Dateiname | Unkomprimierte Größe | Gzip (Verhältnis %) | Brotli (Verhältnis %) |
| jquery-ui-1.12.1.min.js | 247,72 KB | 66,47 KB (26,83%) | 55,8 KB (22,53%) |
| angular-1.6.4.min.js | 163,21 KB | 57,13 KB (35%) | 49,99 KB (30,63%) |
| react-0.14.3.min.js | 118,44 KB | 30,62 KB (25,85%) | 25,1 KB (21,19% |
| jquery-3.2.1.min.js | 84,63 KB | 29,49 KB (34,85%) | 26,63 KB (31,45%) |
| vue-2.3.3.min.js | 77,16 KB | 28,18 KB (36,52%) | |
| zepto-1.2.0.min.js | 25,77 KB | 9,57 KB (37,14%) | |
| preact-8.1.0.min.js | 7,92 KB | 3,31 KB (41,79%) | 3,01 KB (38,01%) |
| rlite-2.0.1.min.js | 1,07 KB | 0,59 KB (55,14%) | 0,5 KB (46,73%) |
Sicher, diese Vergleichstabelle ist übertrieben, aber sie verdeutlicht einen wichtigen Punkt: Große Dateien liefern in der Regel höhere Kompressionsverhältnisse als kleinere. Wenn Sie ein großes Bundle in winzige Stücke aufteilen, erhalten Sie nicht so viel Vorteil durch Komprimierung.
Natürlich ist mehr als die Asset-Größe für die Leistung wichtig. Im Fall von JavaScript möchten wir möglicherweise kleinere, seiten-/templatesspezifische Dateien bevorzugen, da die anfängliche Ladezeit einer bestimmten Seite im Hinblick auf Dateigröße und Parsing-Zeit optimiert wird. Selbst *wenn* diese kleineren Assets nicht individuell komprimiert werden. Persönlich wäre das meine Neigung, wenn ich eine App bauen würde. Bei traditionellen, synchronen "Site"-ähnlichen Erlebnissen neige ich nicht so dazu, Code-Splitting zu verfolgen.
Es gibt jedoch noch mehr zu bedenken als nur JavaScript. Nehmen wir zum Beispiel SVG-Sprites. Wo diese Assets betroffen sind, scheint Bündelung sinnvoller zu sein. Insbesondere für große Sprite-Sets. Ich habe einen grundlegenden Test mit einem *sehr* großen Icon-Set mit 223 Icons durchgeführt. In einem Test habe ich eine gespritet Version des Icon-Sets geliefert. Im anderen habe ich jedes Icon als einzelne Assets geliefert. Im Test mit dem SVG-Sprite macht die Gesamtgröße des Icon-Sets nur knapp 10 KB komprimierte Daten aus. Im Test mit den ungebündelten Assets betrug die Gesamtgröße desselben Icon-Sets *115 KB* komprimierte Daten. Selbst mit Multiplexing gibt es einfach *keine Möglichkeit*, 115 KB bei einer gegebenen Verbindung schneller zu übertragen als 10 KB. Die Komprimierung reicht bei den individualisierten Icons nicht aus, um den Unterschied auszugleichen. *Technischer Hinweis: Die SVG-Bilder wurden in beiden Tests von SVGO optimiert.*
Seitenbemerkung: Ein aufmerksamer Kommentator hat darauf hingewiesen, dass die Firefox-Entwicklertools zeigen, dass im unspriteten Test etwa 38 KB Daten übertragen wurden. Das könnte beeinflussen, wie Sie optimieren. Nur etwas zum Nachdenken.
Browser, die HTTP/2 nicht unterstützen
Ja, das gibt es. Insbesondere Opera Mini scheint hier ein Nachzügler zu sein, und je nach Ihren Benutzern ist dies möglicherweise kein zu ignorierendes Benutzerssegment. Während weltweit etwa 80 % der Menschen mit Browsern surfen, die HTTP/2 unterstützen, sinkt diese Zahl in einigen Ecken der Welt. Allein in Indien nutzen laut caniuse weniger als 50 % der Nutzer einen Browser, der mit HTTP/2-Servern kommunizieren kann. Dies ist zumindest derzeit das Bild, und die Unterstützung ist auf dem Vormarsch, aber wir sind noch weit von einer allumfassenden Unterstützung des Protokolls in Browsern entfernt.
Was passiert, wenn ein Benutzer mit einem Browser, der es nicht unterstützt, mit einem HTTP/2-Server spricht? Der Server greift auf HTTP/1 zurück. Das bedeutet, Sie sind wieder bei den alten Paradigmen der Leistungsoptimierung. Also, wieder: *Machen Sie Ihre Hausaufgaben*. Überprüfen Sie Ihre Analysen und sehen Sie, woher Ihre Benutzer kommen. Besser noch, nutzen Sie die Fähigkeit von caniuse.com, Ihre Analysen zu analysieren und zu sehen, was Ihre Zielgruppe unterstützt.
Der Realitätscheck
Würde irgendein vernünftiger Entwickler sein Frontend so gestalten, dass 223 separate SVG-Bilder geladen werden? Ich hoffe nicht, aber nichts überrascht mich wirklich mehr. In allen, außer den komplexesten und funktionsreichsten Anwendungen, werden Sie Schwierigkeiten haben, so viel Ikonografie zu finden. Aber es könnte für Sie sinnvoller sein, diese Icons in einem Sprite zusammenzufassen und es im Voraus zu laden und die Vorteile einer schnelleren Darstellung bei nachfolgenden Seitenwechseln zu nutzen.
Was mich zur unausweichlichen Schlussfolgerung führt: In den Nischen und Ecken der Web-Performance-Disziplin gibt es keine einfachen Antworten, außer "recherchieren Sie". Verlassen Sie sich auf Analysen, um zu entscheiden, ob Bündelung für Ihre HTTP/2-betriebene Website eine gute Idee ist. Haben Sie viele Benutzer, die nur zu ein oder zwei Seiten gehen und dann gehen? Verschwenden Sie vielleicht keine Zeit mit dem Bündeln von Dingen. Navigieren Ihre Benutzer tief auf Ihrer Website und verbringen dort viel Zeit? Vielleicht bündeln.
Eines ist mir klar: Wenn Sie Ihre für HTTP/1 optimierte Website auf einen HTTP/2-Host verschieben und nichts an Ihrer clientseitigen Architektur ändern, wird das keine große Sache sein. Vertrauen Sie also keinen pauschalen Aussagen von Webentwicklern, die Blogbeiträge schreiben (d. h. mir). Finden Sie heraus, wie *Ihre* Benutzer sich verhalten, welche Optimierungen für *Ihre* Situation am besten geeignet sind und passen Sie *Ihren* Code entsprechend an. Viel Erfolg!
Ich habe es in den Firefox Nightly Developer Tools überprüft. Die Größe des Sprites beträgt „9,55 KB übertragen“, während die Größe der 223 einzelnen SVGs 36,53 KB beträgt. Das ist immer noch eine Erhöhung um den Faktor 3,8. Dies gilt jedoch nur, wenn alle Icons tatsächlich auf der Seite verwendet werden.
223 / 3,8 = ~60. Wenn die Seite also weniger als 60 Icons verwendet, werden weniger KB verbraucht, wenn sie einzeln geladen werden. 60 sollten meiner Meinung nach für jede Seite ausreichen.
Sehr interessant. Chrome zeigt weitaus mehr. Chrome scheint mehr Header zu senden, aber das erklärt nicht das zusätzliche Gewicht.
Sie bringen einen guten Gegenpunkt vor. Ich nehme an, ich habe versucht, etwas Anwendbares für meinen Punkt über Kompressionsverhältnisse einzubringen. Wenn Sie 60 Icons auf mehreren Seiten verteilt haben, aber nie mehr als eine Handvoll auf einer einzelnen Seite verwenden, wäre es sicherlich vorteilhaft, so vorzugehen, wie Sie es sagen.
Aber es könnte auch argumentiert werden, dass das Laden für nachfolgende Seiten beschleunigt werden könnte, wenn Sie diese Bilder im Voraus laden, aber dafür gibt es praktische Argumente dafür und dagegen.
Danke für Ihre Meinung. :)
Dennoch hat die Verwendung von HTTP2 Push mehr Nachteile, da es in verschiedenen Browsern und Betriebssystemen so fehlerhaft ist.
Victor – Könnten Sie die Nachteile / Fehler, die Sie mit HTTP/2 Push erlebt haben, näher erläutern? Ich habe ihn persönlich nicht viel benutzt und bin daran interessiert, mehr darüber zu erfahren, da ich so etwas nicht gehört habe.
Es gibt einen großartigen Artikel von Jake Archibald, der einige Probleme mit HTTP2 Push aufzeigt.
HTTP/2 Server Push ist eher tangential zu diesem Thema, aber nicht völlig unerheblich. Schließlich könnte das Einbetten als eine Form der Bündelung betrachtet werden. Server Push kann die Caching-bezogenen Mängel des Einbettens von Assets beheben und gleichzeitig einen ähnlichen Leistungsvorteil bieten.
Aber das Problem ist, wie Sie sagen, dass Push noch etwas fehlerhaft ist. Jake Archibald hat einen ausgezeichneten Artikel geschrieben, der die Seltsamkeiten von Server Push in verschiedenen Browsern darlegt.
Dennoch hatte ich einige Erfolge mit einem Cookie-basierten Mechanismus im Backend, um redundante Pushes zu vermeiden. Dies scheint für mich recht gut zu funktionieren, ist aber weit davon entfernt, in allen Fällen optimal zu sein.
Danke fürs Lesen. :)
Ja, Sie haben Recht, dass es bei der Implementierung während der Entwicklung der kommenden Website ganz auf das Publikum des Lesers ankommt. Deshalb lohnt es sich auch für Front-End-Entwickler, den Abschnitt Zielgruppe in den Analysen zu prüfen, um diese Fragen zu beantworten, ob HTTP/2 generell gut für die Zielgruppe der kommenden Website sein wird oder nicht.
Mit freundlichen Grüßen,
Mic
Ich glaube nicht, dass jemand wirklich sagt: "Bündeln Sie Ihre Dateien überhaupt nicht". Das dunkle Muster in Bezug auf die Bündelung in HTTP/2 betrifft eher das Laden von Code, der auf einer bestimmten Seite nicht verwendet wird. Wenn Ihre Vorlage/Seite 5 Module verwendet, können Sie diese immer noch zusammen bündeln, bündeln Sie aber einfach keine 10 Module auf einer Seite, die 5 verwendet.
Außerdem können Sie Sprites auch für eine Seite anpassen. Es gibt keinen Grund, eine riesige Sprite-Datei zu haben, wenn Sie nur wenige Icons verwenden. Sie müssen sie nicht in viele Dateien aufteilen, aber Sie müssen auch keine einzige riesige Sprite-Datei haben (ein Mittelweg, wenn Sie so wollen). Mit besserer Header-Komprimierung und Multiplexing werden diese Arten von Build-Modifikationen mit HTTP/2 größere Vorteile bringen.
Nach meinem Verständnis hängt beim HTTP/2 die Wartezeit des Benutzers für eine Gruppe von Bildern vom größten der einzelnen Bilder ab.
Wenn das der Fall ist und das größte meiner SVG-Bilder kleiner ist als der Sprite, der die Gruppe von Bildern enthielt, dann ist es für den Benutzer von Vorteil, wenn die Bilder separat und nicht als Sprite geliefert werden.
Dann habe ich vielleicht etwas übersehen. Es gibt möglicherweise eine maximale Anzahl von Dateien, die unter Multiplexing parallel heruntergeladen werden.