Nie sklejaj plików CSS. Zmierzyłem, ile to kosztuje
Połączenie kilku arkuszy w jeden plik o wadze 69 KB kosztowało mnie 296 ms TBT i 318 ms w styleLayout. Zmianę wycofałem tego samego dnia - poniżej pokazuję, dlaczego jedno długie zadanie parsowania jest gorsze od pięciu krótkich.

👁 118 przeczytań
- Po sklejeniu kilku arkuszy CSS w jeden plik 69 KB TBT na stronie wpisu wzrósł z 76 ms do 372 ms, czyli prawie pięciokrotnie.
- Przy HTTP/2 koszt dodatkowego żądania CSS jest pomijalny, bo multipleksowanie eliminuje kolejkowanie znane z HTTP/1.1.
- Pięć osobnych arkuszy generuje pięć krótkich zadań parsowania, które przeglądarka przeplata z inną pracą, nie przekraczając progu 50 ms liczącego się do TBT.
Skleiłem kilka arkuszy stylów w jeden plik o wadze 69 KB i TBT na stronie wpisu skoczył z 76 do 372 ms. Czas styleLayout wzrósł z 700 do 1018 ms. Zmianę wycofałem, bo poprawa liczby żądań nie zrekompensowała tego, co stało się z wątkiem głównym.
Wniosek w jednym akapicie
Łączenie plików CSS w jeden bundle było sensowną praktyką przy HTTP/1.1, gdzie każde dodatkowe żądanie oznaczało nowe połączenie TCP i miejsce w kolejce ograniczonej do kilku równoległych transferów. Przy HTTP/2 ten koszt w dużej mierze zniknął, a pozostał koszt, o którym stare poradniki nie mówią: parsowanie jednego dużego arkusza to jedno długie zadanie na wątku głównym, którego przeglądarka nie potrafi przerwać. Pięć krótkich zadań parsowania da się przeplatać innymi pracami, jedno długie nie. Moje liczby: TBT 76 ms przed sklejeniem, 372 ms po, styleLayout 700 ms przed, 1018 ms po. To pomiar jednej konfiguracji, nie prawo fizyki - ale wystarczył, żeby cofnąć zmianę.
Co dokładnie zmierzyłem
Punktem wyjścia był typowy stan po kilku latach życia motywu i wtyczek: kilka osobnych arkuszy ładowanych w nagłówku, każdy niewielki. Klasyczna rekomendacja z narzędzi audytowych brzmi w takiej sytuacji „zmniejsz liczbę żądań”, więc zrobiłem to, co robi większość ludzi zajmujących się optymalizacją WordPress - połączyłem je w jeden plik. Wyszło 69 KB.
Mierzyłem stronę wpisu, bo to ona generuje u mnie większość ruchu i ona decyduje o wyniku core web vitals w raportach terenowych. Interesowały mnie dwie rzeczy: Total Blocking Time, czyli ile czasu wątek główny był zajęty zadaniami dłuższymi niż 50 ms, oraz czas styleLayout w profilu wydajności, czyli sumaryczny koszt pracy nad stylami i układem.
| Metryka | Przed sklejeniem | Po sklejeniu w 69 KB | Zmiana |
|---|---|---|---|
| TBT (strona wpisu) | 76 ms | 372 ms | +296 ms |
| styleLayout | 700 ms | 1018 ms | +318 ms |
| Liczba zadań parsowania CSS | 5 krótkich | 1 długie | - |
Prawie pięciokrotny wzrost TBT przy jednoczesnym zmniejszeniu liczby żądań to wynik, który burzy intuicję zbudowaną na poradnikach z poprzedniej dekady. Dlatego warto rozebrać mechanizm.
Dlaczego pięć krótkich zadań bije jedno długie
Przeglądarka wykonuje parsowanie CSS, budowę CSSOM i przeliczanie stylów na wątku głównym - tym samym, na którym wykonuje JavaScript, reaguje na kliknięcia i rysuje klatki. Kluczowa własność: zadanie raz rozpoczęte jest wykonywane do końca. Nie ma wywłaszczenia.
Gdy arkusze są osobne, każdy z nich generuje własne, krótkie zadanie. Między nimi przeglądarka ma okna, w których może obsłużyć coś innego: wykonać fragment skryptu, zareagować na input, oddać klatkę. Pięć krótkich zadań parsowania przeplata się z pozostałą pracą i żadne z nich nie przekracza progu 50 ms, od którego TBT zaczyna cokolwiek liczyć.
Po sklejeniu mam jedno zadanie, które musi przeżuć 69 KB reguł w jednym ciągu. Ono samo przekracza próg i całą swoją długość ponad 50 ms wnosi do TBT. Do tego dochodzi efekt kaskadowy: skoro jedno zadanie trzyma wątek dłużej, zadania stojące za nim w kolejce startują później i częściej wpadają w sytuację, w której konkurują ze sobą. Stąd wzrost styleLayout o 318 ms, mimo że reguł CSS jest dokładnie tyle samo, co przed zmianą. To ta sama praca, tylko upakowana tak, że przeglądarka nie może jej rozłożyć.
Skąd wzięła się porada o sklejaniu
Przy HTTP/1.1 przeglądarka utrzymywała maksymalnie kilka równoległych połączeń na domenę. Szósty plik czekał, aż zwolni się miejsce. Każde połączenie wymagało handshake’u, przy HTTPS dodatkowo negocjacji TLS. W tych warunkach dziesięć małych plików faktycznie było wolniejsze od jednego dużego, nawet jeśli suma bajtów była identyczna - płaciło się za narzut protokołu, nie za treść.
HTTP/2 wprowadził multipleksowanie: wiele strumieni w jednym połączeniu, bez kolejkowania na poziomie żądań. Koszt dodatkowego pliku spadł do wartości, która przy kilku arkuszach jest szumem. Argument za sklejaniem stracił podstawę, ale porada została w narzędziach audytowych i w tysiącach wpisów blogowych. Moja opinia: rekomendacja „zmniejsz liczbę żądań” jest dziś jedną z najbardziej szkodliwych pozostałości po starej epoce, bo brzmi konkretnie i łatwo ją wykonać, a efekt bywa odwrotny do zamierzonego.
Co to znaczy dla TBT i core web vitals
Nie przepłacaj za te subskrypcje
Prowadzę sklep z rocznymi dostępami do narzędzi AI - te same konta, o których piszę wyżej, tylko taniej niż w cenniku producenta.
TBT nie jest metryką terenową w core web vitals - w raportach z realnych urządzeń jej rolę pełni INP. Ale TBT jest najlepszym laboratoryjnym przybliżeniem tego, jak zajęty jest wątek główny, i praktycznie zawsze idzie w tę samą stronę co responsywność na interakcje. Skok z 76 do 372 ms oznacza, że w oknie pomiaru dołożyłem prawie trzy dziesiąte sekundy, w których strona nie odpowiedziałaby na dotknięcie ekranu.
Jeśli ktoś szuka szybkiej ścieżki do tbt poprawa, to rozbicie jednego bundle’a na mniejsze pliki jest w tym pomiarze zabiegiem o efekcie -296 ms, wykonanym bez pisania ani jednej linijki nowego CSS. Nie twierdzę, że u każdego wyjdzie tyle samo. Twierdzę, że warto to zmierzyć przed przyjęciem założenia, że mniej plików znaczy szybciej.
Czego ten pomiar nie pokazuje
Uczciwie o ograniczeniach. Sprawdzałem jeden szablon - stronę wpisu - na jednej instalacji, przy jednym zestawie arkuszy sumujących się do 69 KB. Nie sprawdzałem, gdzie leży próg, przy którym sklejanie przestaje szkodzić: możliwe, że przy dwóch plikach po 3 KB różnicy nie będzie żadnej. Nie sprawdzałem też zachowania przy HTTP/1.1, bo mój serwer go nie używa, ani wpływu na serwerach, gdzie dodatkowe żądanie kosztuje więcej niż u mnie.
Druga rzecz: sklejenie nie zmieniło ilości reguł. Gdyby przy okazji łączenia usunąć martwy CSS, wynik byłby mieszanką dwóch efektów i nie dałoby się ich rozdzielić. Dlatego zmieniałem tylko jedną rzecz naraz - liczbę plików - i tylko o tej jednej rzeczy piszę.
Jak to sprawdzić u siebie
- Zanotuj stan wyjściowy: otwórz DevTools, zakładkę wydajności, nagraj wczytanie strony wpisu z symulacją wolniejszego procesora i zapisz TBT oraz sumaryczny czas styleLayout. Zrób trzy przebiegi i weź medianę, bo pojedynczy pomiar potrafi się rozjechać o kilkadziesiąt milisekund.
- Policz, ile arkuszy CSS realnie ładuje się na tym szablonie i jaka jest ich suma bajtów. To twój punkt odniesienia.
- Sprawdź w kolumnie protokołu w zakładce sieciowej, czy serwer obsługuje HTTP/2. Jeśli tak, argument o oszczędzaniu żądań cię nie dotyczy w takiej formie, w jakiej opisują go stare poradniki.
- Włącz w narzędziu optymalizacyjnym opcję łączenia CSS, wyczyść cache i powtórz pomiar z punktu pierwszego. Tą samą metodą, na tym samym szablonie, w tych samych warunkach dławienia procesora.
- Porównaj dwie rzeczy: TBT oraz najdłuższe pojedyncze zadanie w profilu. Jeśli po sklejeniu pojawiło się jedno zadanie parsowania dłuższe niż wcześniej wszystkie razem, masz dokładnie ten mechanizm, który opisałem.
- Jeśli liczby się pogorszyły, wycofaj zmianę i zostaw arkusze osobno. Ja tak zrobiłem - i do dziś nie mam powodu, by wracać.
- Dopiero po tym zajmij się prawdziwym problemem, czyli objętością CSS. Usunięcie niepotrzebnych reguł zmniejsza pracę do wykonania, a nie tylko przepakowuje ją w inny kształt.
Skąd te liczby
Wszystkie wartości pochodzą z mojego pomiaru na własnej instalacji WordPressa, wykonanego 24.09.2026. Mierzona podstrona: widok pojedynczego wpisu. Testowana zmiana: połączenie kilku osobnych arkuszy stylów w jeden plik o wadze 69 KB, bez modyfikacji zawartości reguł.
Zmierzone wartości - TBT 76 ms przed i 372 ms po, styleLayout 700 ms przed i 1018 ms po - dotyczą tej jednej konfiguracji i nie należy ich traktować jako wartości uniwersalnych. Wyjaśnienie mechanizmu przeplatania pięciu krótkich zadań parsowania wobec jednego długiego oraz ocena rekomendacji o zmniejszaniu liczby żądań to moja interpretacja tych danych. Zmiana została wycofana.
Cały tydzień w AI, w jednym mailu
Wybrane premiery, narzędzia i analizy. Raz w tygodniu, prosto do skrzynki.
Zapisz się za darmo →Najczęstsze pytania
Czy łączenie plików CSS w jeden bundle przyspiesza stronę przy HTTP/2?
Nie - pomiar pokazał pogorszenie TBT o 296 ms i wzrost styleLayout o 318 ms po sklejeniu arkuszy w plik 69 KB. Przy HTTP/2 nie ma kolejkowania żądań jak w HTTP/1.1, więc korzyść z mniejszej liczby plików znika, a koszt jednego długiego zadania parsowania na wątku głównym pozostaje.
Co to jest TBT i dlaczego sklejenie CSS tak bardzo go zwiększa?
TBT - Total Blocking Time - mierzy, ile czasu wątek główny był zajęty zadaniami dłuższymi niż 50 ms. Jeden duży arkusz tworzy jedno nieprzerwane zadanie parsowania przekraczające ten próg, podczas gdy pięć małych plików generuje krótkie zadania, z których żadne progu nie przekracza.
Od kiedy porada o zmniejszaniu liczby żądań CSS jest nieaktualna?
Stała się nieaktualna wraz z upowszechnieniem HTTP/2, który wprowadził multipleksowanie wielu strumieni w jednym połączeniu. Wcześniej przy HTTP/1.1 każdy dodatkowy plik wymagał osobnego połączenia TCP i negocjacji TLS, więc mniej plików faktycznie oznaczało szybsze ładowanie.
Jak samodzielnie sprawdzić, czy sklejenie CSS mi szkodzi?
Należy nagrać wczytanie strony w zakładce wydajności DevTools z symulacją wolniejszego procesora, zapisać TBT i czas styleLayout jako medianę trzech przebiegów, potem włączyć łączenie CSS i powtórzyć pomiar w tych samych warunkach. Jeśli po sklejeniu pojawi się jedno zadanie parsowania dłuższe niż wcześniej wszystkie razem, mechanizm opisany w artykule dotyczy też tej konfiguracji.
