Jednym z najczęstszych problemów decyzyjnych przy tworzeniu front-endu strony internetowej polega na tym czy z punktu widzenia optymalizacji lepiej jest łączyć pliki ze stylami i skryptami (CSS i JS) w jeden plik, rozdzielać na mniejsze fragmenty, czy wklejać w ciało strony. W tym przewodniku postaram się odpowiedzieć na to pytanie oraz dać wskazówki, które spróbują pogodzą zarówno realną wydajność stron internetowych oraz wartości we wszelkiego rodzaju narzędziach do testowania szybkości stron.
Jeżeli interesuje cię temat maksymalizacji wyników w PageSpeed Insights zapraszam do artykułu o tym jak uzyskać 100 punktów w PageSpeed Insights. Wokół tematu narosło wiele mitów i aby w pełni zrozumieć problem musimy najpierw zrozumieć jego tło i odpowiedzieć na fundamentalne pytania.
Uwaga: ten wpis dotyczy sposobu dołączania gotowych plików CSS i JS. Jeżeli interesują cię techniki optymalizacji wydajnościowej kodu CSS i różnych trików polegających na zmniejszeniu blokowania ścieżki krytycznej, czytaj więcej w artykułach:
Dlaczego w ogóle wydzielamy styl i skrypty do osobnych plików CSS i JS?
Zazwyczaj styl i skrypty JavaScript są współdzielone pomiędzy wieloma podstronami. Eksportując je do osobnych plików umożliwiamy dołączenie ich do wielu podstron w wygodny sposób. W przypadku standardowych witryn internetowych prawie zawsze wykorzystujemy ten sam styl i skrypty dlatego eksport kodu CSS i JS jest niejako naturalnym odruchem programisty. Pozwala to wygodnie edytować duże witryny, korzystamy z pamięci podręcznej przeglądarki i oszczędzamy miejsce na serwerze. Podsumujmy korzyści z eksportowania kodu do osobnych plików CSS i JS:
- wygodne zarządzanie kodem – zmiana stylu w jednym pliku automatycznie powoduję zmianę wszystkich podstron, które posiadają odwołanie do tego pliku,
- wygodne prace konserwacyjne – strona z wydzielonymi zasobami jest prostsza w edycji i rozbudowie,
- oszczędność miejsca na serwerze – w przypadku wielu podstron kod odpowiedzialny za styl i skrypty nie są powielane z każdą podstroną tylko dołączane za pomocą kilku znaków,
- oszczędność transferu przy wykorzystaniu pamięci podręcznej – w przypadku skorzystania z nagłówków wygasania (Expires / Cache-Control) jest możliwe szybsze wczytywanie kolejnych podstron ponieważ style CSS i JS nie są pobierane ponownie – są zapisane w lokalnej pamięci urządzenia,
- większa czytelność kodu strony dla robotów – dokumenty HTML, które posiadają większy stosunek treści do kodu są prostsze w przetwarzaniu pod kątem analizy treści,
- mniejszy rozmiar dokumentu HTML – oszczędzają przez to crawl-budget robotów wyszukiwarek.
Kombinacja zasobów w jeden plik
Czasem strona posiada wiele plików CSS – kiedy mamy do czynienia z taką sytuacją? Kiedy instalujemy wtyczki i dodatki (zarówno jeśli chodzi o strony statyczne, wtedy po prostu je dołączamy do kodu lub kiedy mówimy o systemach CMS). Posiadają one swój kod CSS aby nie komplikować oryginalnego stylu CSS i umożliwić wygodną instalację. Strona jest czasem zbudowana z wykorzystaniem gotowych bibliotek np. Bootstrap 4 – ich kod CSS też jest umieszczany zazwyczaj w osobnym pliku. To bardzo pomocne, ponieważ niektóre frameworki i fonty są na tyle popularne, że mogą być współdzielone nawet pomiędzy wieloma witrynami.
Problem zaczyna się wtedy kiedy strona korzysta z protokołu HTTP/1 i tych plików jest bardzo dużo (ponad 20 i więcej). W jednym momencie może być pobierane tylko kilka plików i odwołania do zewnętrznych zasobów dosłownie czekają na swoją kolej.
Można to sprawdzić za pomocą takich narzędzi jak Waterfall w Pingdom Tester. Pokazałem taki diagram w artykule o CDN.
Aby rozwiązać ten problem pliki się łączy, czyli wkleja jedne po drugim – pamiętaj, że kolejność w plikach CSS i JS może mieć wpływ na ich interpretację!
Nie było by w tym nic złego gdyby nie fakt, że wszystkie pliki razem wzięte mogą ważyć nawet powyżej 1 MB. To bardzo dużo – plik taki blokuje wczytywanie się strony. Najpierw musi być pobrany i przetworzony a dopiero potem można wyświetlić treść użytkownikowi dlatego PageSpeed Insights często zgłasza taki problem:

Z tym problemem mamy do czynienia niezależnie od techniki dołączenia stylu CSS, jednak w przypadku dużego pliku spadek wydajności jest znacznie większy.
Drugi problem z kombinacją plików polega na tym, że niektóre skrypty i pliki ze stylami CSS są potrzebne tylko na wyjątkowych podstronach. Łącząc wszystkie skrypty do jednego pliku uniemożliwiamy rozlokowanie specyficznych skryptów tylko na wyjątkowych podstronach co oczywiście może być często marnotrawstwem.
Przykład: skrypt wykorzystywany przy formularza kontaktowych (np. contact-form-7) może być z powodzeniem usunięty na podstronach innych niż „Kontakt”. Przydadzą nam się wówczas instrukcje:
add_action( 'wpcf7_enqueue_styles', function() {wp_deregister_style( 'contact-form-7');}); add_action( 'wpcf7_enqueue_scripts', function() {wp_deregister_script( 'jquery-form' );});
Z takiej funkcji nie skorzystamy jeżeli za pomocą Autoptimize łączymy wszystko w jeden plik lub co gorsza – wklejamy wszystko w ciało dokumentu.
Uwaga: w przypadku serwera obsługującego protokół HTTP/2 kombinacja jest niezalecana. Ponieważ uniemożliwi wykorzystanie priorytetyzacji zasobów i nie przyczynia się do zwiększenia wydajności połączenia. Większość tańszych serwerów obsługuje nadal tylko protokół HTTP/1.
Kombinacja plików może być trudniejsza w serwisach dużej skali. W przypadku odświeżania obiektów w cache plików statycznych aktualizacji musi ulec cały plik a nie np. mniejszy jego fragment, który mógłby być zaktualizowany osobno.
Kombinację plików CSS i JS można też zautomatyzować po stronie serwera (Apache lub nginx) za pomocą modułu pagespeed: https://developers.google.com/speed/pagespeed/module/?hl=pl
Wklejenie CSS i JS w ciało dokumentu HTML
Kiedy należy wklejać kod w ciało strony? Kiedy są to bardzo małe pliki. Musisz pamiętać że każde zapytanie w standardzie HTTP/1 kosztuje. Kosztuje czas, łącze i przede wszystkim zasoby – zarówno serwera jak i klienta. Zanim plik dotrze do Twojej przeglądarki
- przeglądarka musi wysłać żądanie HTTP,
- następuje tzw. handshake SSL,
- transfer żądania,
- serwer musi przygotować odpowiedź i wysłać ją klientowi,
- transfer z powrotem,
- sprawdzenie poprawności danych,
- przetworzenie i zastosowanie w dokumencie.
Pięć pierwszych punktów składa się na opóźnienie określane jako TTFB
Każdy z powyższych punktów zabiera cenny czas dlatego rozsądnym posunięciem jest wklejenie małych plików w ciało dokumentu HTML. Mówimy wtedy o tzw. kodzie inline. Skrypty JavaScript wklejamy w tagi <script> natomiast style CSS wklejamy w znaczniku <style>. Pliki CSS wklejamy zawsze w nagłówku <head>. Wklejenie stylu w innym miejscu jest sprzeczne z dokumentacją W3C.
Stosowanie kodu inline (w ciało strony) jest na tyle efektywną techniką że twórcy Przyspieszonych Stron Mobilnych (AMP) zdecydowali, że będzie to jedyna dozwolona metoda dodawania niestandardowych stylów CSS. Na stronach AMP wymaga się aby styl miał 50KB. Należy pamiętać, że gdyby pozwolono na większy rozmiar kodu cały trik dałby efekt odwrotny do zamierzonego – brak możliwości wykorzystywania pamięci podręcznej przekreśla zasadność tej techniki, ponieważ serwisy z małą wartością współczynnika odrzuceń zużywały by dużo więcej transferu.
JavaScript w nagłówku czy w stopce?
Skrypty JS – jeżeli to możliwe – zawsze wklejamy w stopce przed znacznikiem zamykającym </body>. To pozwala skupić się przeglądarce na załadowaniu treści a dodatkowa funkcjonalność, której załadowanie do DOM może być tymczasowo odroczone, będzie gotowa do działania nieco później.
Jeżeli przeniesienie skryptu z nagłówka do stopki powoduje nieprawidłowe działanie strony oznacza to, że kod zależny od tego skryptu występuje gdzieś wcześniej na stronie (przed stopką). Należy taki kod też w miarę możliwości przenieść do stopki (najlepiej na sam koniec).
Optymalna strategia umieszczania kodu CSS
Aby uzyskać możliwie najwyższą wydajność i wyniki w narzędziach analizujących strony WWW należy:
- małe fragmenty CSS wklejać (inline) w ciało dokumentu HTML w nagłówku, przed znacznikiem zamykającym </head>,
- w przypadku kiedy mamy wiele fragmentów, które nie muszą ulegać częstej aktualizacji, można połączyć w jeden plik,
- Przy wykorzystywaniu protokołu HTTP/1 średniej wielkości pliki CSS łączyć w jeden plik i zamieścić do niego odniesienie w postaci <link rel=”stylesheet” src=”style.css”>,
- Przy wykorzystywaniu protokołu HTTP/2 nie łączyć stylów w jeden pliki CSS i zamieścić do wszystkich plików odniesienie w postaci <link rel=”stylesheet” src=”style.css”>,
- Z wyjątkiem bibliotek (bootstrap, webfonty Google Fonts i fonty ikonowe), stylów dotyczących fontów i dodatków, które nie występują na każdej podstronie lub mogą być współdzielone pomiędzy wieloma serwisami za pomocą oficjalnych CDN.
Optymalna strategia umieszczania skryptów JavaScript
- Małej objętości skrypty JS wklejać w ciało dokumentu HTML w stopce, przed znacznikiem zamykającym </body>,
- w przypadku kiedy takich plików jest bardzo dużo, połączyć je w jednym pliku,
- Przy wykorzystywaniu protokołu HTTP/1, duże i średnie pliki JS łączyć w jeden plik i zamieścić do niego odniesienie w postaci <script src=”script.min.js”>,
- Przy wykorzystywaniu protokołu HTTP/2, nie łączyć plików w jeden plik i zamieszczać je w wielu plikach najlepiej po kilkaset KB w postaci wielu odniesień <script src=”script.min.js”>,
- Wyjątek mogą stanowić biblioteki (np. bootstrap) i skrypty, które mogą być współdzielone z innymi witrynami, (np. analityki, popularne komponenty i skrypty),
- skrypty, które nie są używane na każdej podstronie tez mogą być dołączane w osobnych plikach,
- jeżeli przeniesienie skryptów do stopki spowoduje błędy JS należy przenieść instrukcje zależne jeszcze niżej.
Szczególne przypadki optymalizacji CSS i JS
Wklejenie wszystkich zasobów w ciało strony (poza stronami AMP gdzie jest to wymagane) może być korzystne na:
Ponieważ zazwyczaj nie zachodzi w nich pełne przeładowanie strony.
Inne techniki optymalizacji danych tekstowych
Kod dołączany do stron internetowych można optymalizować także na inne sposoby – o nich stworzyłem osobne artykuły:
- minimalizacja (lub minifikacja),
- kompresja po stronie serwera GZIP/deflate,
- wykorzystanie pamięci podręcznej HTTP (nagłówki Expires i Cache-Control),
- serwer plików statycznych z rozproszoną dystrybucją treści czyli CDN,
- usuwanie nieużywanego kodu CSS.
Podsumowanie
Wykorzystywanie „na wyczucie” wtyczek optymalizujących może nie być najlepszą strategią w próbach zwiększenia wydajności stron WWW. Wskaźniki w różnego rodzaju analizatorach wydajności mogą podpowiadać nieoptymalne ustawienia. Zrozumienie fundamentalnych mechanizmów działania stron internetowych pozwoli na bardziej świadome zwiększenie ich wydajności maksymalizując ogólnie pojęte korzyści z ich stosowania.
Odpowiedz lub skomentuj