Verbesserung von Largest Contentful Paint im gesamten JavaScript-Ökosystem.
Im Rahmen des Projekts Aurora hat Google mit beliebten Webframeworks zusammengearbeitet, um eine gute Leistung gemäß den Core Web Vitals zu gewährleisten. Angular und Next.js unterstützen bereits das Einbetten von Schriftarten, wie im ersten Teil dieses Artikels erläutert. Die zweite Optimierung, die wir behandeln werden, ist das kritische CSS-Inlining, das jetzt standardmäßig in der Angular-Befehlszeile aktiviert ist und in Nuxt.js in der Entwicklungsphase ist.
Einbetten von Schriftarten
Nach der Analyse von Hunderten von Anwendungen stellte das Aurora-Team fest, dass Entwickler häufig Schriftarten in ihre Anwendungen einbinden, indem sie im <head>
-Element von index.html
darauf verweisen. Hier ein Beispiel für die Verwendung von Material Icons:
<!doctype html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
...
</html>
Obwohl dieses Muster völlig gültig und funktionsfähig ist, blockiert es das Rendern der Anwendung und führt zu einer zusätzlichen Anfrage. Sehen wir uns den Quellcode des Stylesheets an, auf das in der obigen HTML-Datei verwiesen wird, um das Problem besser zu verstehen:
/* fallback */
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/font.woff2) format('woff2');
}
.material-icons {
/*...*/
}
Beachten Sie, dass die font-face
-Definition auf eine externe Datei verweist, die auf fonts.gstatic.com
gehostet wird.
Beim Laden der Anwendung muss der Browser zuerst das ursprüngliche Stylesheet herunterladen, auf das im Head verwiesen wird.

Als Nächstes lädt der Browser die woff2
-Datei herunter und kann dann mit dem Rendern der Anwendung fortfahren.

Eine Möglichkeit zur Optimierung besteht darin, das ursprüngliche Stylesheet zum Zeitpunkt des Builds herunterzuladen und in index.html
einzufügen. Dadurch wird bei der Laufzeit ein vollständiger Hin- und Rücklauf zum CDN übersprungen, was die Blockierungszeit verkürzt.
Beim Erstellen der Anwendung wird eine Anfrage an das CDN gesendet. Dadurch wird das Stylesheet abgerufen und in die HTML-Datei eingefügt. Der Domain wird ein <link rel=preconnect>
hinzugefügt. Mit dieser Technik erhalten wir das folgende Ergebnis:
<!doctype html>
<html lang="en">
<head>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin >
<style type="text/css">
@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/font.woff2) format('woff2');}.material-icons{/*...*/}</style>
...
</html>
Inlining von Schriftarten ist jetzt in Next.js und Angular verfügbar
Wenn Framework-Entwickler die Optimierung in den zugrunde liegenden Tools implementieren, können bestehende und neue Anwendungen sie leichter aktivieren und so das gesamte System verbessern.
Diese Verbesserung ist in Next.js v10.2 und Angular v11 standardmäßig aktiviert. Beide unterstützen das Einfügen von Google- und Adobe-Schriftarten. Angular wird Letzteres voraussichtlich in Version 12.2 einführen.
Die Implementierung der Schrift-Inline-Einbindung in Next.js auf GitHub und das Video zur Erklärung dieser Optimierung im Kontext von Angular finden Sie hier.
Kritisches CSS einbetten
Eine weitere Verbesserung besteht darin, die Messwerte First Contentful Paint (FCP) und Largest Contentful Paint (LCP) durch das Einfügen von kritischem CSS zu verbessern. Das kritische CSS einer Seite umfasst alle Stile, die beim ersten Rendern verwendet wurden. Weitere Informationen zu diesem Thema finden Sie unter Nicht kritisches CSS verzögern.
Wir haben festgestellt, dass viele Anwendungen Stile synchron laden, was das Rendern der Anwendung blockiert. Eine schnelle Lösung besteht darin, die Stile asynchron zu laden. Anstatt die Scripts mit media="all"
zu laden, legen Sie den Wert des Attributs media
auf print
fest. Nachdem das Laden abgeschlossen ist, ersetzen Sie den Attributwert durch all
:
<link rel="stylesheet" href="..." media="print" onload="this.media='all'">
Dies kann jedoch zu einem Flackern von nicht formatierten Inhalten führen.
Das Video oben zeigt das Rendern einer Seite, bei der die Stile asynchron geladen werden. Das Flimmern tritt auf, weil der Browser zuerst die Stile herunterlädt und dann die folgende HTML-Datei rendert. Sobald der Browser die Stile heruntergeladen hat, löst er das onload
-Ereignis des Link-Elements aus, aktualisiert das media
-Attribut in all
und wendet die Stile auf das DOM an.
In der Zeit zwischen dem Rendern des HTML-Codes und dem Anwenden der Stile ist die Seite teilweise ohne Stil. Wenn der Browser die Stile verwendet, kommt es zu Flimmern, was die Nutzerfreundlichkeit beeinträchtigt und zu einer Verschlechterung der Cumulative Layout Shift (CLS) führt.
Das Einbetten von kritischem CSS in Kombination mit dem asynchronen Laden von Stilen kann das Ladeverhalten verbessern. Das Tool Critters ermittelt, welche Stile auf der Seite verwendet werden. Dazu werden die Auswahlen in einem Stylesheet mit dem HTML-Code abgeglichen. Wenn eine Übereinstimmung gefunden wird, werden die entsprechenden Stile als Teil des kritischen CSS betrachtet und inline eingefügt.
Beispiel:
<head> <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'"> </head> <body> <section> <button class="primary"></button> </section> </body>
/* styles.css */ section button.primary { /* ... */ } .list { /* ... */ }
Beispiel vor dem Einfügen
Im Beispiel oben lesen und parsen Critter den Inhalt von styles.css
. Anschließend gleichen sie die beiden Auswahlen mit dem HTML-Code ab und stellen fest, dass wir section button.primary
verwenden.
Schließlich fügen die Critter die entsprechenden Stile inline in den <head>
der Seite ein, was zu folgendem Ergebnis führt:
<head> <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'"> <style> section button.primary { /* ... */ } </style> </head> <body> <section> <button class="primary"></button> </section> </body>
Beispiel nach dem Einfügen
Nachdem Sie das kritische CSS in den HTML-Code eingefügt haben, ist das Flackern der Seite verschwunden:
Das Einfügen von kritischen CSS-Dateien ist jetzt in Angular verfügbar und in Version 12 standardmäßig aktiviert. Wenn Sie Version 11 verwenden, setzen Sie die Property inlineCritical
in angular.json
auf true
, um die Funktion zu aktivieren. Wenn Sie diese Funktion in Next.js aktivieren möchten, fügen Sie experimental: { optimizeCss: true }
zu next.config.js
hinzu.
Ergebnisse
In diesem Beitrag haben wir uns mit der Zusammenarbeit zwischen Chrome und Web-Frameworks befasst. Wenn Sie ein Framework-Entwickler sind und einige der Probleme, die wir in Ihrer Technologie angegangen sind, wiedererkennen, hoffen wir, dass unsere Ergebnisse Sie dazu inspirieren, ähnliche Leistungsoptimierungen vorzunehmen.
Weitere Informationen zu den Verbesserungen Eine umfassende Liste der Optimierungen, die wir für Core Web Vitals vorgenommen haben, finden Sie im Beitrag Vorstellung von Aurora.