Eine neuere Webpack-Aufteilungsstrategie in Next.js und Gatsby minimiert Codeduplikaten, um die Leistung beim Laden von Seiten zu verbessern.
Chrome kooperiert mit Tools und Frameworks in der JavaScript-Open-Source-Umgebung. Kürzlich wurden einige Optimierungen wurde hinzugefügt, um die Ladeleistung von Next.js zu verbessern und Gatsby: In diesem Artikel wird eine verbesserte, detaillierte Aufteilungsstrategie behandelt. das jetzt standardmäßig in beiden Frameworks bereitgestellt wird.
Einführung
Wie viele Web-Frameworks verwenden Next.js und Gatsby webpack als Kernstück
Bundler. Einführung von Webpack v3
CommonsChunkPlugin
, damit Sie
Ausgabemodule, die zwischen verschiedenen Einstiegspunkten in einem einzigen (oder wenigen) „Commons“ verwendet werden Chunk (oder
Blöcke). Freigegebener Code kann separat heruntergeladen und frühzeitig im Browser-Cache gespeichert werden.
zu einer besseren Ladeleistung führen.
Dieses Muster wurde bei vielen Single-Page-Frameworks beliebt, die einen Einstiegspunkt und Bundle-Konfiguration so aussieht:
Das Konzept, den gesamten Code aus gemeinsam genutzten Modulen in einem Block zu bündeln, ist zwar praktisch, aber
Einschränkungen. Module, die nicht in jedem Einstiegspunkt freigegeben sind, können für Routen heruntergeladen werden, die sie nicht verwenden
Dadurch wird mehr Code als nötig heruntergeladen. Beispiel: Wenn page1
geladen wird,
dem Chunk common
wird der Code für moduleC
geladen, obwohl page1
moduleC
nicht verwendet.
Aus diesem und einigen anderen Gründen hat Webpack v4 das Plug-in zugunsten eines neuen
1: SplitChunksPlugin
.
Verbesserte Chunking-Methode
Die Standardeinstellungen für SplitChunksPlugin
eignen sich für die meisten Nutzer gut. Mehrere aufgeteilte Blöcke werden
die abhängig von verschiedenen Bedingungen erstellt werden.
um zu verhindern, dass doppelter Code über mehrere Routen hinweg abgerufen wird.
Viele Web-Frameworks, die dieses Plug-in verwenden, folgen jedoch immer noch einem allgemeinen Konzept. Ansatz für Chunk
die Aufteilung. Next.js würde beispielsweise ein commons
-Bundle generieren, das ein beliebiges Modul enthält, das
werden auf mehr als 50% der Seiten und allen Framework-Abhängigkeiten (react
, react-dom
usw.) verwendet.
const splitChunksConfigs = {
…
prod: {
chunks: 'all',
cacheGroups: {
default: false,
vendors: false,
commons: {
name: 'commons',
chunks: 'all',
minChunks: totalPages > 2 ? totalPages * 0.5 : 2,
},
react: {
name: 'commons',
chunks: 'all',
test: /[\\/]node_modules[\\/](react|react-dom|scheduler|use-subscription)[\\/]/,
},
},
},
Obwohl das Einbinden von Framework-abhängigem Code in einen gemeinsamen Block bedeutet, kann dieser heruntergeladen und für jeden Einstiegspunkt, die nutzungsbasierte Heuristik der Einbeziehung allgemeiner Module, die in mehr als auf der Hälfte der Seiten nicht sehr effektiv ist. Die Änderung dieses Verhältnisses würde nur eines von zwei Ergebnissen zur Folge haben:
- Wenn Sie das Verhältnis verringern, wird mehr unnötiger Code heruntergeladen.
- Wenn Sie das Verhältnis erhöhen, wird mehr Code für mehrere Routen dupliziert.
Zur Lösung dieses Problems führte Next.js eine andere
Konfiguration fürSplitChunksPlugin
, die reduzierte
unnötigen Code für jede Route.
- Jedes ausreichend große Drittanbietermodul (größer als 160 KB) wird in ein eigenes Chunk
- Für Framework-Abhängigkeiten (
react
,react-dom
undframeworks
so weiter) - Es werden so viele freigegebene Blöcke wie nötig erstellt (bis zu 25).
- Die Mindestgröße für einen zu generierenden Block wird in 20 KB geändert
Diese detaillierte Aufteilungsstrategie bietet folgende Vorteile:
- Die Seitenladezeiten wurden verbessert. Werden mehrere freigegebene Blöcke anstelle eines einzelnen Blöcke ausgegeben, minimiert die Menge an unnötigem (oder doppeltem) Code für einen Einstiegspunkt.
- Verbessertes Caching während der Navigation: Große Bibliotheken und Framework-Abhängigkeiten aufteilen in separate Blöcke unterteilt, was die Wahrscheinlichkeit einer Cache-Entwertung verringert, da es bei beiden unwahrscheinlich ist, bis ein Upgrade durchgeführt wird.
Sie können die gesamte Konfiguration sehen, die Next.js in webpack-config.ts
übernommen hat.
Mehr HTTP-Anfragen
SplitChunksPlugin
hat die Grundlage für die detaillierte Aufteilung definiert und diesen Ansatz auf eine
wie Next.js kein völlig neues Konzept war. Viele Konzepte wurden jedoch
eine einzige Heuristik und „Commons“ für eine einheitliche Bündelung. Dazu gehört auch die Sorge,
und mehr HTTP-Anfragen
die Websiteleistung beeinträchtigen können.
Browser können nur eine begrenzte Anzahl von TCP-Verbindungen zu einem einzigen Ursprung (6 für Chrome) öffnen. Durch das Minimieren der Anzahl von Blöcken, die von einem Bundler ausgegeben werden, kann sichergestellt werden, unter diesem Grenzwert bleibt. Dies gilt jedoch nur für HTTP/1.1. Multiplexing in HTTP/2 können mehrere Anfragen parallel gestreamt werden, wobei eine Verbindung über eine einzige Ursprung. Mit anderen Worten: Wir brauchen uns in der Regel keine Gedanken über die Begrenzung der Anzahl der Blöcke zu machen. die von unserem Bundler ausgegeben werden.
Alle gängigen Browser unterstützen HTTP/2. Die Chrome- und Next.js-Teams
wollte herausfinden, ob die Anzahl der Anfragen durch Aufteilung der einzelnen "Commons" von Next.js erhöht würde. Set
die die Ladeleistung beeinträchtigen würden. Sie begannen mit der Messung der
Leistung einer einzelnen Website erzielen und gleichzeitig die maximale Anzahl paralleler Anfragen mithilfe der Funktion
maxInitialRequests
Property.
Bei durchschnittlich drei Durchläufen mehrerer Tests auf einer einzelnen Webseite
load
,
start-render
und First Contentful Paint-Zeiten blieben alle ungefähr gleich, wenn das maximale
Anzahl der Anfragen (von 5 bis 15). Interessanterweise stellten wir nur einen geringen Leistungsaufwand fest.
nach einer aggressiven Aufteilung auf Hunderte von Anfragen.
Es zeigte sich, dass das Halten eines zuverlässigen Schwellenwerts (20–25 Anfragen) das richtige Gleichgewicht war.
zwischen Ladeleistung und Caching-Effizienz. Nach einigen Ausgangstests wurden 25 als
Anzahl der maxInitialRequest
.
Wenn Sie die maximale Anzahl paralleler Anfragen ändern, wurden mehrere und die sinnvolle Trennung für die einzelnen Einstiegspunkte reduzierten die nicht benötigten Code für dieselbe Seite generiert.
Bei diesem Test ging es nur darum, die Anzahl der Anfragen zu ändern, um zu ermitteln,
negative Auswirkungen auf die Seitenladeleistung. Laut den Ergebnissen sollte maxInitialRequests
auf
25
auf der Testseite war optimal, da dadurch die Größe der JavaScript-Nutzlast reduziert wurde, ohne dass dies zu einer Verlangsamung führte.
auf der Seite nach unten. Die Gesamtmenge an JavaScript, die zur Bereitstellung der Seite erforderlich war, blieb weiterhin bestehen.
Das erklärt, warum sich die Ladegeschwindigkeit aufgrund der geringeren
die Menge an Code.
Webpack verwendet 30 KB als Standard-Mindestgröße für einen zu erstellenden Block. Das Koppeln eines
Der maxInitialRequests
-Wert von 25 mit einer Mindestgröße von 20 KB führte stattdessen zu einem besseren Caching.
Größenreduzierungen mit detaillierten Blöcken
Viele Frameworks, einschließlich Next.js, nutzen für die Injektion clientseitiges Routing (von JavaScript verarbeitet). neuere Skript-Tags für jeden Routenübergang. Aber wie werden diese dynamischen Blöcke bei der Build-Erstellung vorab festgelegt?
Next.js bestimmt anhand einer serverseitigen Build-Manifestdatei, welche ausgegebenen Blöcke von unterschiedlichen Einstiegspunkten. Um auch dem Kunden diese Informationen zur Verfügung zu stellen, wird eine clientseitige Kurzfassung angezeigt. Build-Manifestdatei erstellt wurde, um alle Abhängigkeiten für jeden Einstiegspunkt zuzuordnen.
// Returns a promise for the dependencies for a particular route
getDependencies (route) {
return this.promisedBuildManifest.then(
man => (man[route] && man[route].map(url => `/_next/${url}`)) || []
)
}
Diese neuere, detaillierte Aufteilungsstrategie wurde erstmals in Next.js hinter einem Flag eingeführt, wo sie auf einem der ersten Nutzer. Bei vielen Unternehmen sank die Anzahl der JavaScript-Elemente, die für ihre gesamte Website:
Website | JS-Gesamtänderung | Unterschied in % |
---|---|---|
https://www.barnebys.com/ | -238 KB | -23% |
https://sumup.com/ | -220 KB | -30% |
https://www.hashicorp.com/ | -11 MB | -71% |
Die endgültige Version wurde standardmäßig in Version 9.2 ausgeliefert.
Gatsby
Gatsby verfolgte den gleichen Ansatz wie die Verwendung einer nutzungsbasierten Heuristik zum Definieren gängiger Module:
config.optimization = {
…
splitChunks: {
name: false,
chunks: `all`,
cacheGroups: {
default: false,
vendors: false,
commons: {
name: `commons`,
chunks: `all`,
// if a chunk is used more than half the components count,
// we can assume it's pretty global
minChunks: componentsCount > 2 ? componentsCount * 0.5 : 2,
},
react: {
name: `commons`,
chunks: `all`,
test: /[\\/]node_modules[\\/](react|react-dom|scheduler)[\\/]/,
},
Durch die Optimierung der Webpack-Konfiguration für eine ähnliche, detaillierte Aufteilungsstrategie erhebliche JavaScript-Reduzierung bei vielen großen Websites festgestellt:
Website | JS-Gesamtänderung | Unterschied in % |
---|---|---|
https://www.gatsbyjs.org/ | -680 KB | -22% |
https://www.thirdandgrove.com/ | -390 KB | -25 % |
https://ghost.org/ | -1,1 MB | -35% |
https://reactjs.org/ | -80 KB | -8 % |
In der Öffentlichkeitsarbeit erfahren Sie, wie sie implementiert diese Logik in ihrer Webpack-Konfiguration, die standardmäßig in Version 2.20.7 ausgeliefert wird.
Fazit
Das Konzept des Versands von detaillierten Blöcken ist nicht spezifisch für Next.js, Gatsby oder sogar Webpack. Alle sollten erwägen, die Aufteilungsstrategie ihrer Anwendung zu verbessern, wenn sie einem großen allgemeinen Konzept folgt. Bundle-Ansatz, unabhängig vom verwendeten Framework oder Modul-Bundler.
- Wenn Sie die gleichen Segmentierungsoptimierungen auf eine einfache React-Anwendung anwenden möchten, Sehen Sie sich dieses React-Beispiel App. Dabei wird ein vereinfachte Version der detaillierten Aufteilungsstrategie und hilft Ihnen, mit Logik auf Ihrer Website.
- Für Rollup werden Blöcke standardmäßig im Detail erstellt. Sehen Sie sich
manualChunks
, wenn Sie manuell Änderungen vornehmen möchten konfigurieren Sie das Verhalten.