Wprowadzenie: ścieżka krytyczna — wąskie gardło, o którym wszyscy zapominają
W poprzednich artykułach z serii Web Perf Clinic przeszliśmy przez Core Web Vitals 2026, optymalizację bundli JavaScript, strategie cachowania, optymalizację obrazów i czcionki webowe. Każdy z tych elementów wpływa na szybkość strony — ale jest jeden mechanizm, który tak naprawdę decyduje o tym, kiedy użytkownik w ogóle zobaczy cokolwiek na ekranie. Mówię o krytycznej ścieżce renderowania (Critical Rendering Path, CRP).
CRP to sekwencja kroków, które przeglądarka musi wykonać, zanim wyświetli pierwszy piksel. Brzmi prosto, prawda? Problem w tym, że jeśli na tej ścieżce leży zbyt wiele zasobów blokujących — CSS, JavaScript, czcionki — użytkownik widzi białą stronę przez setki milisekund dłużej niż powinien. A to bezpośrednio przekłada się na gorsze wyniki First Contentful Paint (FCP) i Largest Contentful Paint (LCP).
Żeby dać trochę perspektywy — według danych HTTP Archive z początku 2026 roku, mediana strony mobilnej ładuje ponad 70 KB skompresowanego CSS i 6–8 zewnętrznych arkuszy stylów. Każdy z nich blokuje renderowanie. To dużo.
W tym artykule pokażę, jak drastycznie skrócić krytyczną ścieżkę — od ręcznego wyodrębniania Critical CSS, przez automatyzację z Beasties, po nowoczesne techniki jak content-visibility: auto i CSS @layer. No to zaczynajmy.
Czym dokładnie jest krytyczna ścieżka renderowania?
Krytyczna ścieżka renderowania to seria kroków, które przeglądarka wykonuje od momentu otrzymania pierwszych bajtów HTML do wyświetlenia pikseli na ekranie. Oto te kroki w skrócie:
- Parsowanie HTML → DOM — przeglądarka buduje drzewo Document Object Model z kodu HTML.
- Parsowanie CSS → CSSOM — równolegle buduje CSS Object Model ze wszystkich arkuszy stylów.
- Wykonanie JavaScript — skrypty mogą modyfikować zarówno DOM, jak i CSSOM, co wymaga wstrzymania parsowania.
- Budowa drzewa renderowania — połączenie DOM i CSSOM w drzewo elementów widocznych na ekranie.
- Layout — obliczenie pozycji i wymiarów każdego elementu.
- Paint — rysowanie pikseli w pamięci.
- Composite — złożenie warstw i wyświetlenie na ekranie.
I tutaj jest sedno sprawy: przeglądarka nie wyświetli niczego, dopóki nie ukończy kroków 1–4. Każdy zasób, który blokuje którykolwiek z tych kroków, wydłuża czas do pierwszego renderowania. Google nazywa takie zasoby render-blocking resources — i szczerze mówiąc, ich eliminacja to jeden z najszybszych sposobów na poprawę FCP.
CSS jako zasób blokujący renderowanie
CSS jest domyślnie zasobem blokującym renderowanie. Dlaczego? Ponieważ reguły CSS mogą być nadpisywane — przeglądarka musi pobrać i przetworzyć cały arkusz stylów, zanim będzie mogła zbudować kompletny CSSOM. Dopóki CSSOM nie jest gotowy, renderowanie po prostu stoi.
W praktyce wygląda to tak: jeśli masz w <head> pięć linków do arkuszy CSS:
<link rel="stylesheet" href="/css/reset.css">
<link rel="stylesheet" href="/css/typography.css">
<link rel="stylesheet" href="/css/layout.css">
<link rel="stylesheet" href="/css/components.css">
<link rel="stylesheet" href="/css/utilities.css">
…to przeglądarka musi pobrać wszystkie pięć plików i przetworzyć je, zanim wyświetli cokolwiek. Nawet jeśli 80% reguł CSS dotyczy elementów poniżej pierwszego ekranu (below the fold), przeglądarka i tak musi na nie poczekać. Trochę absurdalne, ale tak to działa.
Jak zidentyfikować zasoby blokujące renderowanie?
Najszybszy sposób to Lighthouse — audit „Eliminate render-blocking resources" pokaże dokładnie, które pliki CSS i JS blokują renderowanie, wraz z szacunkowym oszczędzonym czasem po ich usunięciu. Dodatkowo, w Chrome DevTools zakładka Coverage (Ctrl+Shift+P → „Show Coverage") pokaże procentowo, ile kodu CSS z każdego pliku jest faktycznie używane na bieżącej stronie. Wyniki potrafią zaskoczyć.
Critical CSS — inline'owanie stylów krytycznych
Okej, skoro wiemy, na czym polega problem, przejdźmy do rozwiązania. Critical CSS to technika, w której wyodrębniamy minimalny zestaw reguł CSS potrzebnych do wyświetlenia zawartości widocznej w pierwszym ekranie (above the fold) i umieszczamy je bezpośrednio w <style> w <head>. Resztę CSS ładujemy asynchronicznie.
Efekt? Przeglądarka ma wszystkie potrzebne style od razu, bez czekania na zewnętrzne pliki. W praktyce poprawia to FCP o 500 ms–2 sekundy — w zależności od rozmiaru oryginalnych arkuszy i prędkości połączenia. Na wolniejszym 3G? Różnica bywa jeszcze większa.
Krok po kroku: ręczne wdrożenie Critical CSS
Krok 1: Wyodrębnij krytyczne reguły. Zidentyfikuj style, które dotyczą elementów widocznych w początkowym widoku (viewport) — nagłówek, menu nawigacyjne, sekcja hero, pierwszy blok treści.
Krok 2: Umieść je inline w <head>.
<head>
<style>
/* Critical CSS — style dla above the fold */
body { margin: 0; font-family: system-ui, sans-serif; }
.header { background: #1a1a2e; color: #fff; padding: 1rem; }
.hero { min-height: 60vh; display: grid; place-items: center; }
.hero h1 { font-size: clamp(2rem, 5vw, 3.5rem); }
</style>
</head>
Krok 3: Załaduj resztę CSS asynchronicznie. Tu jest klasyczny trick z atrybutem media="print":
<link rel="stylesheet" href="/css/full.css" media="print" onload="this.media='all'">
<noscript>
<link rel="stylesheet" href="/css/full.css">
</noscript>
Przeglądarka pobierze plik full.css z niskim priorytetem (bo media="print" nie pasuje do bieżącego kontekstu), a po załadowaniu zmieni media na all, co zastosuje style. Proste i skuteczne.
Budżet na Critical CSS: poniżej 14 KB
To ważne — inline CSS nie powinien przekroczyć 14 KB po kompresji. Dlaczego akurat 14 KB? To przybliżony rozmiar danych, które mogą być przesłane w pierwszym TCP round trip (przy oknie kongestii ~10 segmentów × 1460 bajtów). Jeśli Critical CSS zmieści się w tym limicie, przeglądarka otrzyma wszystkie krytyczne style w pierwszej odpowiedzi serwera — bez potrzeby dodatkowych round tripów. Każdy dodatkowy round trip to zazwyczaj 50–100 ms opóźnienia, a na mobilnych sieciach nawet więcej.
Automatyzacja Critical CSS z Beasties (następca Critters)
Ręczne zarządzanie Critical CSS w dużych projektach to — powiedzmy sobie szczerze — koszmar. Zmieniasz jeden komponent, a cały inline CSS może wymagać aktualizacji. Na szczęście są narzędzia, które automatyzują ten proces.
W 2026 roku rekomendowanym rozwiązaniem jest Beasties — aktywnie rozwijany fork Critters (oryginalny projekt Google Chrome Labs jest zarchiwizowany od jakiegoś czasu).
Beasties vs. inne narzędzia
Beasties nie uruchamia headless browser — analizuje statycznie HTML i CSS, co czyni go znacznie szybszym niż alternatywy oparte na Puppeteer (np. pakiet critical od Addy Osmani). Jest tu pewien kompromis: Beasties inline'uje wszystkie reguły CSS używane w dokumencie, a nie tylko te widoczne above the fold. Ale w praktyce, dla aplikacji SPA z prerenderingiem, to i tak idealne rozwiązanie.
Konfiguracja z Vite
// vite.config.ts
import { defineConfig } from 'vite';
import beasties from 'vite-plugin-beasties';
export default defineConfig({
plugins: [
beasties({
options: {
preload: 'swap',
pruneSource: true,
mergeStylesheets: true,
},
}),
],
});
Konfiguracja z Webpack
// webpack.config.js
const Beasties = require('beasties-webpack-plugin');
module.exports = {
plugins: [
new Beasties({
preload: 'swap',
pruneSource: true,
}),
],
};
Po zbudowaniu projektu Beasties automatycznie wyodrębni krytyczne style CSS i umieści je inline w <head>, przekształci linki do arkuszy CSS w lazy-loading z media="print" i opcjonalnie usunie z arkuszy zewnętrznych reguły, które zostały inline'owane (pruneSource: true). Całość działa w tle, bez konieczności ręcznej interwencji.
Kontrola za pomocą komentarzy
Fajną funkcją jest możliwość wymuszenia lub wykluczenia konkretnych reguł z Critical CSS:
/* beasties:exclude */
.modal-backdrop {
/* ten selektor nigdy nie trafi do Critical CSS */
background: rgba(0, 0, 0, 0.5);
}
/* beasties:include */
.above-fold-banner {
/* ten selektor zawsze trafi do Critical CSS */
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
Eliminacja blokujących zasobów JavaScript
CSS to nie jedyny winowajca. JavaScript domyślnie blokuje parsowanie HTML (parser-blocking) — przeglądarka musi pobrać, sparsować i wykonać skrypt, zanim może kontynuować budowanie DOM. Dlatego kluczowe są atrybuty async i defer:
<!-- Blokujący — unikaj w <head> -->
<script src="/js/app.js"></script>
<!-- Async — pobiera równolegle, wykonuje natychmiast po pobraniu -->
<script src="/js/analytics.js" async></script>
<!-- Defer — pobiera równolegle, wykonuje po sparsowaniu HTML -->
<script src="/js/app.js" defer></script>
Kiedy używać async, a kiedy defer?
defer— dla głównego kodu aplikacji. Gwarantuje wykonanie w kolejności i po zakończeniu parsowania DOM. Szczerze? To powinien być Twój domyślny wybór w 2026 roku.async— dla niezależnych skryptów, które nie modyfikują DOM (analytics, tracking, reklamy). Kolejność wykonania nie jest gwarantowana, więc nie polegaj na nim przy skryptach, które od siebie zależą.
Skrypty third-party — szczególne wyzwanie
Skrypty zewnętrzne (Google Analytics, chat widgets, tagi reklamowe) to wiecznie żywy problem. Dodają dodatkowe żądania DNS, połączenia TLS i czas wykonania. Oto strategie, które naprawdę działają:
preconnect— nawiąż połączenie do domeny zewnętrznej z wyprzedzeniem:
<link rel="preconnect" href="https://www.google-analytics.com" crossorigin>
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
- Odroczone ładowanie — ładuj skrypty third-party dopiero po interakcji użytkownika (np. po pierwszym scrollu lub kliknięciu). Sam stosuję tę technikę i różnica w FCP potrafi być imponująca:
const loadThirdParty = () => {
const script = document.createElement('script');
script.src = 'https://example.com/widget.js';
script.async = true;
document.body.appendChild(script);
// Usuń listener po pierwszym wywołaniu
window.removeEventListener('scroll', loadThirdParty);
};
window.addEventListener('scroll', loadThirdParty, { once: true });
content-visibility: auto — ukryta supermoc CSS
Właściwość content-visibility: auto to moim zdaniem jedna z najbardziej niedocenianych optymalizacji renderowania w 2026 roku. I wreszcie (wreszcie!) od września 2025 jest wspierana przez wszystkie główne przeglądarki — Chrome, Firefox, Safari, Edge. Można ją śmiało stosować w produkcji.
Jak działa?
content-visibility: auto informuje przeglądarkę, że może pominąć renderowanie elementów, które nie są widoczne w viewporcie. Przeglądarka stosuje automatycznie containment (izolację) — pomija layout, paint i compositing dla elementów poza ekranem. Gdy użytkownik scrolluje w ich kierunku, przeglądarka renderuje je na czas. Takie sprytne leniwe renderowanie, ale wbudowane w silnik przeglądarki.
Wyniki w praktyce
W benchmarkach na stronach z dużą ilością treści, zastosowanie content-visibility: auto do sekcji poniżej pierwszego ekranu skróciło czas renderowania z 232 ms do 30 ms. To 7-krotna poprawa na początkowym załadowaniu — i to bez żadnych zmian w HTML czy JavaScript.
Co więcej, poprawia się także LCP, ponieważ przeglądarka może skupić się na renderowaniu tego, co naprawdę ważne.
Implementacja
/* Zastosuj do sekcji poniżej pierwszego ekranu */
.section-below-fold {
content-visibility: auto;
contain-intrinsic-size: auto 500px;
}
/* Przykład: lista artykułów, komentarze, stopka */
.article-list > article:nth-child(n+3) {
content-visibility: auto;
contain-intrinsic-size: auto 300px;
}
.comments-section {
content-visibility: auto;
contain-intrinsic-size: auto 800px;
}
footer {
content-visibility: auto;
contain-intrinsic-size: auto 200px;
}
Kluczowe zasady
- Zawsze dodawaj
contain-intrinsic-size— bez tego przeglądarka potraktuje element jako mający zerową wysokość, co spowoduje skoki przewijania i pogorszenie CLS. Wartośćauto 500pxoznacza: „użyj zapamiętanego rozmiaru, a jeśli go nie masz, załóż 500 px". - Nie stosuj do elementów above the fold — przeglądarka może przez chwilę pokazać puste miejsce, zanim wyrenderuje treść. Używaj wyłącznie dla zawartości poniżej viewportu.
- Dostępność jest zachowana — elementy ukryte przez
content-visibility: autonadal istnieją w DOM i drzewie dostępności. Wyszukiwanie na stronie (Ctrl+F), nawigacja tabulatorem i czytniki ekranowe działają normalnie. Bez niespodzianek.
CSS @layer — kaskadowe warstwy jako narzędzie wydajności
CSS @layer (Cascade Layers) to stosunkowo nowa funkcja CSS z ponad 96% wsparciem przeglądarek w 2026 roku. Jej głównym celem jest zarządzanie kaskadą, ale ma też ciekawe zastosowanie wydajnościowe, o którym mało kto mówi.
Separacja krytycznego i niekrytycznego CSS
Warstwy pozwalają jawnie oddzielić Critical CSS od reszty, co ułatwia zarówno automatyzację, jak i utrzymanie kodu:
/* Definiuj kolejność warstw na samym początku */
@layer reset, critical, components, utilities;
/* Reset — najniższy priorytet */
@layer reset {
*, *::before, *::after { box-sizing: border-box; margin: 0; }
}
/* Critical — style above the fold */
@layer critical {
.header { background: #1a1a2e; color: #fff; padding: 1rem; }
.hero { min-height: 60vh; display: grid; place-items: center; }
}
/* Components — ładowane asynchronicznie */
@layer components {
.card { border: 1px solid #e2e8f0; border-radius: 0.5rem; }
.modal { position: fixed; inset: 0; z-index: 100; }
}
/* Utilities — najwyższy priorytet w warstwach */
@layer utilities {
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; }
.hidden { display: none; }
}
Style w warstwie critical mogą być inline'owane w <head>, podczas gdy warstwy components i utilities ładowane są asynchronicznie. A co najlepsze — warstwy eliminują problemy ze specyficznością. Style w wyższej warstwie zawsze wygrywają, niezależnie od złożoności selektora. Koniec z !important hacks (i dobrze).
Optymalizacja CSS media queries
Prosty, ale zaskakująco często pomijany trick: rozdzielenie CSS na pliki z odpowiednimi atrybutami media. Przeglądarka pobierze wszystkie pliki, ale tylko te pasujące do bieżącego kontekstu będą blokować renderowanie:
<!-- Blokuje renderowanie — zawsze potrzebne -->
<link rel="stylesheet" href="/css/core.css">
<!-- Nie blokuje na desktopie -->
<link rel="stylesheet" href="/css/mobile.css" media="(max-width: 768px)">
<!-- Nie blokuje na ekranie -->
<link rel="stylesheet" href="/css/print.css" media="print">
<!-- Nie blokuje w jasnym motywie -->
<link rel="stylesheet" href="/css/dark.css" media="(prefers-color-scheme: dark)">
Przeglądarka pobierze plik print.css z niskim priorytetem i nie zablokuje renderowania, ponieważ atrybut media nie pasuje do bieżącego kontekstu (ekran, nie drukarka). To samo dotyczy mobile.css na szerokim ekranie i dark.css w jasnym motywie. Minimalna zmiana, a mniej zasobów blokuje renderowanie.
Unikaj @import w CSS
Dyrektywa @import w CSS to, nie przesadzając, cichy zabójca wydajności. Tworzy łańcuch zależności — przeglądarka nie wie o importowanym pliku, dopóki nie pobierze i nie sparsuje pliku nadrzędnego:
/* styles.css */
@import url('reset.css'); /* Przeglądarka dowiaduje się o tym pliku dopiero teraz */
@import url('typography.css'); /* Czeka na reset.css, potem pobiera ten */
@import url('layout.css'); /* Czeka na typography.css... */
Widzisz problem? Zamiast pobrać trzy pliki równolegle, przeglądarka pobiera je jeden po drugim. Rozwiązanie? Zamiast @import, używaj oddzielnych tagów <link> w HTML:
<link rel="stylesheet" href="/css/reset.css">
<link rel="stylesheet" href="/css/typography.css">
<link rel="stylesheet" href="/css/layout.css">
Jeszcze lepiej — połącz te pliki w jeden plik za pomocą bundlera (Vite, Webpack, esbuild), aby zredukować liczbę żądań HTTP. Jedno żądanie zamiast trzech to zawsze wygrana.
103 Early Hints — przyśpieszanie dostarczania krytycznych zasobów
HTTP 103 Early Hints to mechanizm, o którym wciąż mało kto wie, a który potrafi zdziałać cuda. Pozwala serwerowi wysłać nagłówki z podpowiedziami jeszcze zanim wygeneruje właściwą odpowiedź. Serwer odpowiada kodem 103, wskazując przeglądarce zasoby do pobrania z wyprzedzeniem, a dopiero potem wysyła pełną odpowiedź 200.
HTTP/1.1 103 Early Hints
Link: </css/critical.css>; rel=preload; as=style
Link: </fonts/inter.woff2>; rel=preload; as=font; crossorigin
HTTP/1.1 200 OK
Content-Type: text/html
...
To szczególnie przydatne, gdy serwer potrzebuje czasu na wygenerowanie HTML (dynamiczne strony, SSR). Zamiast marnować ten czas na czekanie, przeglądarka już pobiera krytyczne CSS i czcionki. Według danych Chrome, strony korzystające z 103 Early Hints osiągają p75 TTFB bliskie 0 ms dla nawigacji z prerenderingiem. Naprawdę warto to wdrożyć.
Audytowanie krytycznej ścieżki renderowania
Teoria teorią, ale jak to wygląda w praktyce? Oto workflow do audytu CRP, który sam stosuję w swoich projektach:
1. Lighthouse — szybki przegląd
Uruchom audyt Lighthouse (zakładka Performance w DevTools lub PageSpeed Insights). Szukaj trzech rzeczy:
- „Eliminate render-blocking resources" — lista CSS i JS blokujących renderowanie z szacunkowym oszczędzonym czasem.
- „Reduce unused CSS" — ile CSS z pobranych plików jest faktycznie używane.
- „Avoid chaining critical requests" — wizualizacja łańcuchów zależności (np. CSS → @import → kolejny CSS).
2. Chrome DevTools Coverage
Otwórz Coverage (Ctrl+Shift+P → „Show Coverage"), załaduj stronę i sprawdź, jaki procent każdego pliku CSS jest używany. Typowy wynik? 60–80% kodu CSS jest nieużywane na danej stronie. Tak, poważnie — to całkiem normalne i jednocześnie pokazuje, ile jest tu potencjału do optymalizacji.
3. WebPageTest — waterfall analysis
WebPageTest oznacza zasoby blokujące renderowanie pomarańczowym kółkiem. Analizuj diagram waterfall — szukaj zasobów, które opóźniają Start Render i FCP. Szczególnie zwracaj uwagę na łańcuchy: HTML → CSS → @import → font.
4. Performance API w kodzie
Do monitoringu na produkcji używaj Performance API — dzięki temu masz realne dane od użytkowników, nie tylko syntetyczne testy:
// Mierzenie czasu blokowania renderowania
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.renderBlockingStatus === 'blocking') {
console.log(
`Zasób blokujący: ${entry.name}`,
`Czas: ${entry.duration.toFixed(0)} ms`
);
}
}
});
observer.observe({ type: 'resource', buffered: true });
// FCP — kiedy użytkownik widzi pierwszy piksel
new PerformanceObserver((list) => {
const fcp = list.getEntries()[0];
console.log(`FCP: ${fcp.startTime.toFixed(0)} ms`);
}).observe({ type: 'paint', buffered: true });
Checklist optymalizacji CRP na 2026 rok
Na koniec — podsumowanie wszystkich technik w formie checklisty. Możesz ją potraktować jako plan działania dla swojego projektu:
- Wyodrębnij i inline'uj Critical CSS (maks. 14 KB skompresowane) w
<head>. - Załaduj resztę CSS asynchronicznie za pomocą techniki
media="print". - Zautomatyzuj proces z Beasties (Vite lub Webpack).
- Dodaj
deferdo wszystkich skryptów w<head>. - Użyj
preconnectdla domen zewnętrznych (CDN, analytics). - Zastosuj
content-visibility: autodo sekcji poniżej pierwszego ekranu. - Zastąp
@importoddzielnymi tagami<link>lub bundlowaniem. - Rozdziel CSS z media queries, aby zmniejszyć ilość CSS blokującego renderowanie.
- Skonfiguruj 103 Early Hints na serwerze dla krytycznych zasobów.
- Monitoruj FCP i render-blocking resources za pomocą Performance API na produkcji.
Najczęściej zadawane pytania (FAQ)
Czym jest krytyczna ścieżka renderowania i dlaczego wpływa na szybkość strony?
Krytyczna ścieżka renderowania (CRP) to sekwencja kroków, które przeglądarka musi wykonać, aby przekształcić HTML, CSS i JavaScript w piksele na ekranie. Obejmuje budowanie DOM, CSSOM, drzewa renderowania oraz layout i paint. Każdy zasób blokujący na tej ścieżce — np. zewnętrzny arkusz CSS lub synchroniczny skrypt JS — wydłuża czas do wyświetlenia pierwszej treści (FCP). Optymalizacja CRP sprowadza się do zmniejszenia liczby zasobów blokujących, ich rozmiaru i głębokości łańcuchów zależności.
Jak wyodrębnić Critical CSS bez narzędzi automatycznych?
Otwórz Chrome DevTools, przejdź do zakładki Coverage (Ctrl+Shift+P → „Show Coverage") i załaduj stronę. Zobaczysz, które reguły CSS są używane na bieżącej stronie. Skopiuj reguły oznaczone jako używane, które dotyczą elementów widocznych w pierwszym viewporcie. Umieść je w tagu <style> w <head>, a pełny arkusz załaduj asynchronicznie. Dla większych projektów zdecydowanie polecam automatyzację za pomocą Beasties — ręczne zarządzanie szybko staje się niewykonalne.
Czy content-visibility: auto jest bezpieczne do użycia na produkcji w 2026 roku?
Tak, jak najbardziej. Od września 2025 roku content-visibility jest wspierane przez wszystkie główne przeglądarki — Chrome, Firefox, Safari i Edge. W 2026 roku można bezpiecznie stosować tę właściwość w produkcji. Pamiętaj tylko o dwóch rzeczach: dodaj contain-intrinsic-size, aby uniknąć problemów z CLS, i nie stosuj jej do elementów widocznych w pierwszym ekranie.
Jakie jest praktyczne znaczenie limitu 14 KB dla Critical CSS?
Limit 14 KB wynika z działania protokołu TCP — to przybliżona ilość danych, która może być przesłana w pierwszym round trip (przy oknie kongestii ~10 segmentów). Jeśli Critical CSS zmieści się w tym limicie, przeglądarka otrzyma krytyczne style razem z HTML w pierwszej odpowiedzi serwera, bez potrzeby dodatkowych cykli połączenia. Przekroczenie tego limitu oznacza dodatkowe opóźnienie, więc warto pilnować, żeby inline'ować tylko naprawdę krytyczne reguły.
Czy async i defer w skryptach JavaScript naprawdę poprawiają renderowanie?
Zdecydowanie tak. Bez tych atrybutów skrypt w <head> blokuje parsowanie HTML — przeglądarka musi pobrać, sparsować i wykonać skrypt, zanim zbuduje resztę DOM. Atrybut defer pozwala pobierać skrypt równolegle z parsowaniem HTML i wykonuje go dopiero po zakończeniu parsowania. Atrybut async także pobiera równolegle, ale wykonuje natychmiast po pobraniu. W obu przypadkach parsowanie HTML nie jest blokowane, co bezpośrednio skraca czas do FCP.