Das Laden großer JavaScript-Ressourcen beeinträchtigt die Seitengeschwindigkeit erheblich. Wird aufgeteilt in kleinere Teile aufteilen und nur das herunterladen, Eine Seite, die beim Start funktioniert, kann die Ladegeschwindigkeit Ihrer Seite erheblich verbessern. Reaktionszeit, was sich wiederum positiv auf die Interaktion mit dem nächsten Video Paint (INP):
Wenn eine Seite große JavaScript-Dateien herunterlädt, analysiert und kompiliert, über einen bestimmten Zeitraum nicht mehr reagieren. Die Seitenelemente sind sichtbar, da sie Teil des anfänglichen HTML-Codes einer Seite und mit CSS formatiert ist. Da JavaScript jedoch die zum Betreiben dieser interaktiven Elemente erforderlich sind, sowie anderer Skripts, die von parst und führt sie JavaScript aus, damit sie funktionieren. Die Das Ergebnis ist, dass die Nutzenden das Gefühl haben, dass die Interaktion verzögert oder sogar völlig kaputt ist.
Dies passiert häufig, weil der Hauptthread beim Parsen von JavaScript blockiert wird. und im Hauptthread kompiliert. Wenn dieser Vorgang zu lange dauert, Seitenelemente möglicherweise nicht schnell genug auf Nutzereingaben reagieren. Eine Abhilfe in diesem Fall nur den JavaScript-Code zu laden, der für das Funktionieren der Seite erforderlich ist, während Verzögern des Ladens anderer JavaScript-Elemente mithilfe einer Technik, die als Code bezeichnet wird die Aufteilung. In diesem Modul konzentrieren wir uns auf die letztere dieser beiden Methoden.
JavaScript-Parsing und -Ausführung beim Start durch Codeaufteilung reduzieren
Lighthouse gibt eine Warnung aus, wenn die Ausführung von JavaScript länger als zwei Sekunden und schlägt fehl, wenn es länger als 3,5 Sekunden dauert. Übermäßiges JavaScript das Parsen und die Ausführung stellen an jeder Stelle auf der Seite ein potenzielles Problem dar Lebenszyklus, da er die Eingabeverzögerung einer Interaktion erhöhen kann. wenn der Zeitpunkt, zu dem der Nutzer mit der Seite interagiert, mit dem Moment übereinstimmt. sind die Hauptthreadaufgaben, die für die Verarbeitung und Ausführung von JavaScript verantwortlich sind, ausgeführt wird.
Darüber hinaus ist übermäßiges Ausführen und Parsen von JavaScript beim ersten Seitenaufbau problematisch, da dies der Punkt auf der Seite ist, dass Nutzer mit hoher Wahrscheinlichkeit mit der Seite interagieren. Tatsächlich Die Gesamtblockierungszeit (Total Blocking Time, TBT), ein Messwert für die Reaktionsfähigkeit bei Lasten, steht in einer starken Korrelation mit INP, was darauf hindeutet, dass Nutzer*innen eine hohe Tendenz zu Interaktionen haben beim ersten Seitenaufbau an.
Die Lighthouse-Prüfung, in der der Zeitaufwand für die Ausführung der einzelnen JavaScript-Dateien erfasst wird dass Ihre Seitenanforderungen nützlich sind, da Sie so genau ermitteln können, Scripts eignen sich möglicherweise für die Codeaufteilung. Sie können dann weiter gehen, indem Sie mit dem Tool für die Abdeckung in den Chrome-Entwicklertools, um genau zu ermitteln, das JavaScript einer Seite beim Laden der Seite nicht verwendet wird.
Codeaufteilung ist eine nützliche Technik, mit der die anfängliche JavaScript-Größe einer Seite reduziert werden kann. Payloads. Damit können Sie ein JavaScript-Bundle in zwei Teile aufteilen:
- Entspricht dem JavaScript-Code, der beim Seitenaufbau benötigt wird und daher nicht auf anderen .
- Verbleibendes JavaScript, das meistens zu einem späteren Zeitpunkt geladen werden kann der Punkt, an dem die Nutzenden mit einem bestimmten interaktiven Element auf auf der Seite.
Codeaufteilung kann mithilfe der dynamischen import()
-Syntax erfolgen. Dieses
Syntax (im Gegensatz zu <script>
-Elementen, die eine bestimmte JavaScript-Ressource anfordern).
beim Start: Eine JavaScript-Ressource wird zu einem späteren Zeitpunkt während
Seitenlebenszyklus.
document.querySelectorAll('#myForm input').addEventListener('blur', async () => {
// Get the form validation named export from the module through destructuring:
const { validateForm } = await import('/validate-form.mjs');
// Validate the form:
validateForm();
}, { once: true });
Im vorherigen JavaScript-Snippet ist das Modul validate-form.mjs
nur dann heruntergeladen, geparst und ausgeführt, wenn ein Nutzer eines der Elemente eines Formulars unkenntlich gemacht hat.
<input>
-Felder. In diesem Fall kann die JavaScript-Ressource,
Die Validierungslogik des Formulars spielt nur dann eine Rolle,
tatsächlich verwendet wird.
JavaScript-Bundler wie webpack, Parcel, Rollup und esbuild können
JavaScript-Bundles immer in kleinere Blöcke aufzuteilen,
dass ein dynamischer Aufruf von import()
in Ihrem Quellcode angezeigt wird. Die meisten dieser Tools
Dies geschieht automatisch, aber insbesondere für
Optimierung.
Hilfreiche Hinweise zum Aufteilen von Code
Codeaufteilung ist zwar eine effektive Methode, um Konflikte im Hauptthread zu reduzieren Beim ersten Seitenaufbau zahlt es sich aus, einige Dinge zu beachten, wenn Sie entscheiden, um Ihren JavaScript-Quellcode auf Möglichkeiten zur Codeaufteilung zu überprüfen.
Verwenden Sie, wenn möglich, einen Bundler.
Es ist üblich, dass Entwickler JavaScript-Module während der und Entwicklungsprozessen. Es ist eine hervorragende Verbesserung der Entwicklererfahrung, verbessert die Lesbarkeit und Verwaltbarkeit des Codes. Es gibt jedoch einige suboptimale Leistungsmerkmale, die sich beim Versand von JavaScript bis hin zur Produktion.
Am wichtigsten ist, dass Sie einen Bundler zur Verarbeitung und Optimierung Ihrer Quelle verwenden. und Module, die Sie aufteilen möchten. Bundler sind sehr effektiv, Optimierungen werden nicht nur auf den JavaScript-Quellcode angewendet, sondern sind auch ist sehr effektiv bei der Abwägung von Leistungsaspekten wie der Bundle-Größe. gegenüber dem Verdichtungsverhältnis. Die Effektivität der Komprimierung erhöht sich mit der Bundle-Größe, Bundler achten aber auch darauf, dass Pakete nicht so groß sind, zu langen Aufgaben aufgrund der Skriptauswertung.
Bundler vermeiden außerdem das Problem, dass eine große Anzahl entbündelter Module versendet wird.
über das Netzwerk. Architekturen, die JavaScript-Module
verwenden, haben meist große,
und komplexe Modulbäume. Bei der Entbündelung von Modulbäumen stellt jedes Modul ein
HTTP-Anfrage getrennt. Die Interaktivität in Ihrer Webanwendung kann sich verzögern,
bündeln Sie keine Module. Mit der Funktion
<link rel="modulepreload">
-Ressourcenhinweis zum frühzeitigen Laden großer Modulstrukturen
JavaScript-Bundles immer noch gegenüber Ladeleistungen vorzuziehen,
Standpunkt.
Deaktiviere nicht versehentlich die Streaming-Kompilierung
Die V8-JavaScript-Engine von Chromium bietet eine Reihe standardmäßiger Optimierungen. damit Ihr Produktions-JavaScript-Code so effizient wie möglich geladen wird. Eine dieser Optimierungen wird als Streaming-Kompilierung bezeichnet. inkrementelles Parsen von HTML-Code, der an den Browser gestreamt wird – kompiliert gestreamte Blöcke wenn sie vom Netzwerk empfangen werden.
Sie haben mehrere Möglichkeiten, sicherzustellen, dass eine Streaming-Kompilierung für Ihr Konto erfolgt. Webanwendung in Chromium:
- Transformieren Sie Ihren Produktionscode, um JavaScript-Module zu vermeiden. Bündel Ihren JavaScript-Quellcode basierend auf einem Kompilierungsziel umwandeln und ist das Ziel oft umgebungsspezifisch. V8 wendet Streaming an Kompilierung in JavaScript-Code, der keine Module verwendet, und Sie können Bundler so konfigurieren, dass der Code des JavaScript-Moduls in eine Syntax umgewandelt wird der keine JavaScript-Module nutzt.
- Wenn Sie JavaScript-Module an die Produktion senden möchten, verwenden Sie die
.mjs
Erweiterung. Unabhängig davon, ob Ihr Produktions-JavaScript Module verwendet oder nicht, Kein spezieller Inhaltstyp für JavaScript, der Module statt JavaScript verwendet aber das ist nicht der Fall. Bei V8 wird das Streaming effektiv deaktiviert. Kompilierung, wenn du JavaScript-Module in der Produktion mit der.js
sendest . Wenn Sie die Erweiterung.mjs
für JavaScript-Module verwenden, kann V8 dass die Streaming-Kompilierung für modulbasierten JavaScript-Code kaputt.
Lassen Sie sich von diesen Überlegungen nicht davon abhalten, Codeaufteilung zu verwenden. Code ist eine effektive Methode, um die anfängliche JavaScript-Nutzlast für Nutzende zu reduzieren. Wenn Sie einen Bundler verwenden und wissen, wie Sie das Streaming von V8 Kompilierungsverhalten haben, können Sie sicherstellen, dass Ihr JavaScript-Produktionscode genauso so schnell für die Nutzenden, wie es sein kann.
Dynamischer Import – Demo
Webpack
webpack wird mit dem Plug-in SplitChunksPlugin
ausgeliefert, mit dem Sie
konfigurieren, wie der Bundler JavaScript-Dateien aufteilt. erkennt Webpack sowohl die
dynamische import()
- und statische import
-Anweisungen. Das Verhalten von
SplitChunksPlugin
kann geändert werden, indem die Option chunks
in der zugehörigen
Konfiguration:
chunks: async
ist der Standardwert und bezieht sich auf dynamischeimport()
-Aufrufe.chunks: initial
bezieht sich auf statischeimport
-Aufrufe.chunks: all
deckt sowohl dynamischeimport()
- als auch statische Importe ab, sodass Sie um Blöcke fürasync
- undinitial
-Importe freizugeben.
Standardmäßig immer dann, wenn Webpack auf eine dynamische import()
-Anweisung stößt. sie
einen separaten Chunk für dieses Modul:
/* main.js */
// An application-specific chunk required during the initial page load:
import myFunction from './my-function.js';
myFunction('Hello world!');
// If a specific condition is met, a separate chunk is downloaded on demand,
// rather than being bundled with the initial chunk:
if (condition) {
// Assumes top-level await is available. More info:
// https://v8.dev/features/top-level-await
await import('/form-validation.js');
}
Die Standard-Webpack-Konfiguration für das vorherige Code-Snippet führt zu zwei separate Blöcke:
- Dem
main.js
-Chunk, der von Webpack alsinitial
-Block klassifiziert wird, enthält das Modulmain.js
und./my-function.js
. - Der Block
async
, der nurform-validation.js
enthält (mit einem Datei-Hash im Ressourcennamen, falls konfiguriert. Dieser Block wird nur heruntergeladen wenncondition
wahrheit ist.
Mit dieser Konfiguration können Sie das Laden des Blocks form-validation.js
verzögern, bis
tatsächlich benötigt wird. Dies kann die Reaktionsfähigkeit beim Laden verbessern, indem das Script
Bewertungszeit beim ersten Seitenaufbau an. Skriptdownload und -auswertung
für den Block form-validation.js
tritt auf, wenn eine bestimmte Bedingung erfüllt ist, in
In diesem Fall wird das dynamisch
importierte Modul heruntergeladen. Ein Beispiel könnte ein
wenn ein Polyfill nur für einen bestimmten Browser heruntergeladen wird.
aus dem vorherigen Beispiel: Das importierte Modul ist für eine Nutzerinteraktion erforderlich.
Wenn Sie jedoch die SplitChunksPlugin
-Konfiguration ändern, um
Mit chunks: initial
wird sichergestellt, dass der Code nur auf die ersten Blöcke aufgeteilt wird. Dies sind
Blöcke wie statisch importierte oder in der Datei entry
des Webpacks aufgelistete Blöcke
. Im vorherigen Beispiel wäre der resultierende Chunk ein
Kombination aus form-validation.js
und main.js
in einer Skriptdatei
Dies kann die Leistung beim ersten Seitenaufbau verschlechtern.
Die Optionen für SplitChunksPlugin
können auch so konfiguriert werden, dass größere
Skripts in mehrere kleinere aufteilen, z. B. mit der Option maxSize
, um Webpack anzuweisen, Blöcke in separate Dateien aufzuteilen, wenn diese die
angegeben durch maxSize
. Das Unterteilen großer Skriptdateien in kleinere Dateien
Verbessern der Lastenreaktion, z. B. in einigen Fällen CPU-intensiver Skriptauswertung
in kleinere Aufgaben aufgeteilt ist, bei denen die Hauptaufgabe
für längere Zeit verwenden.
Größere JavaScript-Dateien bedeuten auch, dass Skripts ist die Wahrscheinlichkeit einer Cache-Entwertung höher. Wenn Sie zum Beispiel eine das Framework und eigenen Anwendungscode enthält, Das Bundle kann ungültig werden, wenn nur das Framework aktualisiert wird, aber nichts anderes in der gebündelten Ressource.
Andererseits erhöhen kleinere Skriptdateien die Wahrscheinlichkeit, ruft der Besucher Ressourcen aus dem Cache ab, was zu einem schnelleren Laden der Seiten auf wiederholte Besuche. Kleinere Dateien profitieren jedoch weniger von der Komprimierung als größere und kann die Netzwerk-Umlaufzeit beim Laden von Seiten mit einer Browser-Cache. Es ist wichtig, ein Gleichgewicht zwischen dem Caching Effizienz, Komprimierung und die Zeit der Skriptauswertung.
<ph type="x-smartling-placeholder">Webpack-Demo
<ph type="x-smartling-placeholder">Webpack SplitChunksPlugin
-Demo
Wissen testen
Der Typ der import
-Anweisung, die beim Ausführen von Code verwendet wird
Aufteilung?
import()
.import
.
Welche Art von import
-Anweisung muss sich ganz oben befinden
eines JavaScript-Moduls und an keiner anderen Stelle?
import()
.import
.
Was ist bei der Verwendung von SplitChunksPlugin
in Webpack
zwischen einem async
-Chunk und einem
Block initial
?
async
Blöcke werden mit dem dynamischen import()
geladen
und initial
-Blöcke werden mithilfe einer statischen
import
.
async
Chunks werden mit dem statischen import
geladen
und initial
-Blöcke werden mit dynamischen
import()
.
Nächster Schritt: Lazy Loading von Bildern und <iframe>
-Elementen
Auch wenn es sich um einen ziemlich teuren Ressourcentyp handelt, ist JavaScript nicht
Ressourcentyp, dessen Laden Sie verschieben können. Bild und <iframe>
-Elemente
sind für sich genommen möglicherweise kostspielige Ressourcen. Ähnlich wie bei JavaScript können Sie
kann das Laden von Bildern und <iframe>
-Elementen durch Lazy Loading verzögern.
, was im nächsten Modul dieses Kurses erklärt wird.