Verbetering van de grootste Contentful Paint in het JavaScript-ecosysteem.
In het kader van het project Aurora heeft Google samengewerkt met populaire webframeworks om ervoor te zorgen dat ze goed presteren volgens Core Web Vitals . Angular en Next.js hebben al font inlining geïmplementeerd, wat wordt uitgelegd in het eerste deel van dit artikel. De tweede optimalisatie die we zullen bespreken, is kritieke CSS-inlining, die nu standaard is ingeschakeld in de Angular CLI en momenteel wordt geïmplementeerd in Nuxt.js.
Lettertype-inlining
Na analyse van honderden applicaties ontdekte het Aurora-team dat ontwikkelaars vaak lettertypen in hun applicaties opnemen door ernaar te verwijzen in het <head>
-element van index.html
. Hier is een voorbeeld van hoe dit eruit zou zien met Material Icons:
<!doctype html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
...
</html>
Hoewel dit patroon volledig geldig en functioneel is, blokkeert het de weergave van de applicatie en introduceert het een extra verzoek. Om beter te begrijpen wat er gebeurt, bekijk de broncode van de stylesheet waarnaar in de bovenstaande HTML wordt verwezen:
/* 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 {
/*...*/
}
Merk op hoe de font-face
verwijst naar een extern bestand dat gehost wordt op fonts.gstatic.com
. Bij het laden van de applicatie moet de browser eerst de originele stylesheet downloaden waarnaar in de head wordt verwezen.

Vervolgens downloadt de browser het woff2
bestand en kan vervolgens de applicatie worden weergegeven.

Een optimalisatiemogelijkheid is om de initiële stylesheet tijdens de build te downloaden en in te voegen in index.html
. Dit slaat een volledige roundtrip naar het CDN tijdens runtime over, waardoor de blokkeringstijd wordt verkort.
Tijdens het bouwen van de applicatie wordt een verzoek naar het CDN gestuurd. Dit haalt de stylesheet op en plaatst deze in het HTML-bestand, waarbij een <link rel=preconnect>
aan het domein wordt toegevoegd. Met deze techniek zouden we het volgende resultaat krijgen:
<!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>
Lettertype-inlining is nu beschikbaar in Next.js en Angular
Wanneer frameworkontwikkelaars optimalisatie implementeren in de onderliggende tooling, maken ze het eenvoudiger voor bestaande en nieuwe applicaties om dit mogelijk te maken. Dit brengt de verbetering met zich mee voor het gehele ecosysteem.
Deze verbetering is standaard ingeschakeld vanaf Next.js v10.2 en Angular v11. Beide bieden ondersteuning voor inlining van Google- en Adobe-lettertypen. Angular verwacht deze laatste te introduceren in v12.2.
De implementatie van font inlining in Next.js vindt u op GitHub . Bekijk ook de video waarin deze optimalisatie in de context van Angular wordt uitgelegd .
Kritische CSS inline plaatsen
Een andere verbetering betreft het verbeteren van de First Contentful Paint (FCP) en Largest Contentful Paint (LCP) statistieken door kritieke CSS te integreren. De kritieke CSS van een pagina bevat alle stijlen die bij de eerste weergave zijn gebruikt. Lees meer over dit onderwerp in Defer non-critical CSS .
We hebben geconstateerd dat veel applicaties stijlen synchroon laden, waardoor het renderen van de applicatie wordt geblokkeerd. Een snelle oplossing is om de stijlen asynchroon te laden. In plaats van de scripts te laden met media="all"
, stelt u de waarde van het media
-attribuut in op print
en vervangt u de attribuutwaarde door all
zodra het laden is voltooid:
<link rel="stylesheet" href="..." media="print" onload="this.media='all'">
Deze praktijk kan echter leiden tot het knipperen van niet-opgemaakte content.
De video hierboven toont de rendering van een pagina, waarbij de stijlen asynchroon worden geladen. Het flikkeren ontstaat doordat de browser eerst de stijlen downloadt en vervolgens de HTML-code rendert die daarop volgt. Zodra de browser de stijlen downloadt, activeert hij de onload
-gebeurtenis van het linkelement, waarbij het media
attribuut wordt bijgewerkt naar all
en de stijlen worden toegepast op de DOM.
In de tijd tussen het renderen van de HTML en het toepassen van de stijlen is de pagina gedeeltelijk ongestyled. Wanneer de browser de stijlen gebruikt, zien we flikkeringen, wat een slechte gebruikerservaring is en resulteert in regressies in Cumulative Layout Shift (CLS) .
Kritieke CSS-inlining , samen met asynchroon laden van stijlen, kan het laadgedrag verbeteren. De Critters- tool vindt welke stijlen op de pagina worden gebruikt door de selectors in een stylesheet te bekijken en deze te vergelijken met de HTML. Wanneer er een match wordt gevonden, beschouwt de tool de corresponderende stijlen als onderdeel van de kritieke CSS en worden ze inline geplaatst.
Laten we eens naar een voorbeeld kijken:
<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 { /* ... */ }
Voorbeeld vóór inline.
In het bovenstaande voorbeeld lezen en parseren Critters de inhoud van styles.css
, waarna ze de twee selectors vergelijken met de HTML en ontdekken dat we section button.primary
gebruiken. Ten slotte plaatsen Critters de corresponderende stijlen in de <head>
van de pagina, wat resulteert in:
<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>
Voorbeeld na inline.
Nadat u de kritische CSS in de HTML hebt inline gezet, zult u merken dat het knipperen van de pagina is verdwenen:
Kritische CSS-inlining is nu beschikbaar in Angular en standaard ingeschakeld in v12. Als je v11 gebruikt, kun je dit inschakelen door de eigenschap inlineCritical in angular.json
inlineCritical
true
in te stellen . Om deze functie in Next.js te gebruiken, voeg je het volgende toe experimental: { optimizeCss: true }
aan je next.config.js
.
Conclusies
In dit bericht hebben we een aantal aspecten van de samenwerking tussen Chrome en webframeworks besproken. Als u een frameworkontwikkelaar bent en enkele van de problemen herkent die we in uw technologie hebben aangepakt, hopen we dat onze bevindingen u inspireren om soortgelijke prestatie-optimalisaties toe te passen.
Lees meer over de verbeteringen . Een uitgebreid overzicht van de optimalisatiewerkzaamheden die we voor Core Web Vitals hebben uitgevoerd, vindt u in het bericht Introductie van Aurora .