W tym artykule zamieszczę techniki optymalizacji strony WordPress pod PageSpeed i Core Web Vitals, które stosuję w ramach powdrożeniowej optymalizacji stron oraz podczas usługi optymalizacji wydajnościowej WordPressa. Zastosowanie wszystkich technik da pewność osiągniecia najwyższego wyniku w konkretnych warunkach czyli wykorzystując szablon A na hostingu B z krytycznymi wtyczkami C. Termin krytyczna wtyczka to stworzone dla potrzeb tego artykułu pojęcie oznaczające wtyczkę, której nie można ani wyłączyć, zamienić na inną wtyczkę, ani dopisać jej funkcjonalności we własnej wtyczce lub szablonie. Często taką wtyczką jest WooCommerce – odpowiada ona za działanie sklepu internetowego.
W tym artykule nie będzie porad typu: „wyłącz niepotrzebne wtyczki”, „zoptymalizuj zdjęcia”, „zmień hosting”, „wykorzystaj CDN” lub „włącz wtyczkę XYZ WP Optimizer”. Tego typu porady, jak sam wiesz dają wątpliwe efekty lub pomogą Ci jeżeli celujesz w wynik 50/100.
Być może jest tak, że Twoja strona WordPress w wyniku optymalizacji osiąga już zielony wynik mobilny w PageSpeed Insights – wtedy zastosowanie tych technik może zwiększyć wynik do wyniku 100/100 lub spełnić Core Web Vitals nie tylko w wybranych stronach ale we wszystkich. Zobacz jak wygląda wykres podstawowych wskaźników internetowych, kiedy wszystkie podstrony spełniają te warunki:

To jest stan do którego będziemy dążyli. Wynik naszej strony WordPress w PageSpeed Insights jest tylko naszym drogowskazem gdzie i jakie można jeszcze wykonać usprawnienia dla spełnienia Core Web Vitals.
Aby poprawnie zoptymalizować stronę WordPress pod kątem PageSpeed i podstawowych wskaźników Internetowych trzeba przestrzegać kilku prostych zasad dzięki czemu trafnie zdiagnozujemy wąskie gardła, rezultaty prac będą przewidywalne i zminimalizujemy czasochłonność procedur związanych z nanoszeniem poprawek optymalizacyjnych.
- Testując stronę w serwisie PageSpeed Insights symulujemy „normalne” odwiedziny na stronie z włączonym Cache upewniając się, że mógł się wygenerować przy wizycie. W praktyce wygląda to tak, że przed testem w PageSpeed Insights wchodzimy na stronę jako użytkownik niezalogowany, czyli z okna Incognito (lub prywatnego).
- Za faktyczny wynik w PageSpeed Insights uznajemy średnią z trzech testów następujących po sobie. Tym bardziej, jeżeli wynik w PSI mocno się waha przy kolejnych testach.
- Do optymalizacji nie używamy żadnych „wtyczek optymalizujących” poza oczywistymi wtyczkami Cache. Efekty działania optymalizacji czy to styli czy skryptów utrudniają prawdziwą optymalizację, są nieprzewidywalne, często powodują nieprawidłowe wyświetlanie się strony. Minimalizacja wszystkich plików CSS i JS nie ma sensu i pamiętaj, że nigdy nie możemy wykonywać na stronie WordPress żadnych zmian, których sami nie rozumiemy. Inżynieria wsteczna ich funkcjonowania często przekracza koszt napisania sobie samemu potrzebnych funkcji.
- Do samodzielnego wykonania prac optymalizacyjnych i zrozumienia wskazówek w tym tutorialu trzeba dysponować chociaż podstawową znajomością działania stron internetowych i programowania w środowisku WordPress. Nie ma sensu aby optymalizacji podejmowała się osoba, która nie wie co to jest functions.php albo nie znała podstaw składni CSS lub JS. Optymalizując stronę WordPress musimy dysponować umiejętnościami co najmniej takimi jakimi dysponował twórca aktualnie wykorzystywanego motywu. Optymalizacja to poprawa świadomie lub nieświadomie popełnionych błędów i zaniedbań twórców wykorzystywanego motywu i wtyczek.
Spis treści:
- Wyświetlaj obrazy w formatach nowej generacji
- Odłóż ładowanie obrazów poza ekranem
- Ogranicz wpływ kodu spoza witryny
- Zmień rozmiar obrazów
- Użyj efektywnego kodowania obrazów
- Użyj formatów wideo dla animacji
- Ogranicz nieużywany kod CSS
- Ogranicz nieużywany JavaScript
- Wyeliminuj zasoby blokujące renderowanie
- Skróć wstępny czas reakcji serwera
- Wyświetlaj zasoby statyczne, stosując efektywne zasady pamięci podręcznej
- Zapewnij widoczność tekstu podczas ładowania czcionek internetowych
- Unikaj zbyt dużego DOM
Wyświetlaj obrazy w formatach nowej generacji – WordPress

Aby spełnić ten punkt trzeba zamieszczać na stronie i w szablonie obrazki w formacie WebP lub innym formacie nowej generacji. Teoretycznie, można ręcznie wysyłać pliki przekonwertowane na WebP do odpowiednik folderów /wp-uploads/ i dodać odpowiednie reguły .htaccess / nginx.conf, które zamieściłem poniżej – jednak może to być czasochłonne i mało wygodne. Wysyłanie do biblioteki WordPress zdjęć w formacie WebP nie zapewni szerokiej kompatybilności.
Optymalną procedurą będzie wykorzystanie wtyczki EWWW Image Optimizer z następującymi ustawieniami:

Następnie regenerujemy obrazki:

Przepisywanie i detekcja obsługi WebP w Apache
W przypadku hostingów Apache do pliku .htaccess dodajemy następujące reguły jeżeli wtyczka ich nie dodała automatycznie:
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTP_ACCEPT} image/webp RewriteCond %{REQUEST_FILENAME} (.*).(jpe?g|png)$ RewriteCond %{REQUEST_FILENAME}.webp -f RewriteRule (.+).(jpe?g|png)$ %{REQUEST_FILENAME}.webp [T=image/webp,E=accept:1] </IfModule> <IfModule mod_headers.c> Header append Vary Accept env=REDIRECT_accept </IfModule> AddType image/webp .webp
Oczywiście, aby to działało nie można mieć aktywnego Cloudflare i innych podobnych usług działających na zasadzie odwrotnego serwera pośredniczącego (ang. Reverse Proxy).
Przepisywanie i detekcja obsługi WebP w nginx
W przypadku serwera nginx trzeba wykonać następujące kroki. W pliku /etc/nginx/nginx.conf w bloku http{} wstawiamy dyrektywę map:
map $http_accept $webp_suffix { default ""; "~*webp" ".webp"; }
Nowe wersje nginx powinny rozpoznawać WebP na wszelki wypadek dodajmy taki wpis do pliku mime.types:
image/webp webp;
Ostatnim krokiem będzie edycja pliku /etc/nginx/sites-enabled/default. W bloku server{} dodajemy:
location ~* ^.+\.(png|jpe?g)$ { add_header Vary Accept; try_files $uri$webp_suffix $uri =404; }
Jeżeli nie możesz dodać instrukcji, korzystasz z hostingu zarządzanego lub dodanie instrukcji nie działa, skontaktuj się z dostawcą hostingu aby poinstruował cię jak włączyć przepisywanie obrazków na format WebP. Jeżeli dostawca nie zapewnia takiej funkcjonalności i odmawia pomocy, jest to dość mocny argument aby zmienić hosting. a w niektórych hostingach takie przekierowanie już działa i nie trzeba wykonywać żadnych działań – wystarczy tylko wykonać test czy działa to prawidłowo. Przeciągamy zdjęcie ze strony na pulpit – jeżeli ściągnęliśmy jpg.webp lub png.webp mimo, że w kodzie strony i w adresie url mamy .jpg lub .png to przekierowanie działa.
Odłóż ładowanie obrazów poza ekranem – WordPress

Kolejny problem związany z obrazkami jaki może zgłosić PageSpeed po przetestowaniu naszej strony WordPress może polegać na braku wykorzystania techniki lazy-loading dla zdjęć, grafik i filmów. Tak jak pisałem w artykule Optymalizacja obrazów w WordPressie, system ten od wersji 5.4 dodaje domyślnie atrybut loading=”lazy” do znaczników img. Jeżeli korzystamy z aktualnego systemu WordPress nadal ten problem może występować w przypadku niezoptymalizowanych szablonów, które używają ręcznie zakodowanych znaczników img oraz funkcji get_attachment_image_src(), która zwraca same ścieżki do obrazków.
Problem ten jest też często napotykany w stronach, które wyświetlają zdjęcie w postaci tła bannera lub slajderów za pomocą stylu inline:
<section style="background-image:url('wp-contents/uploads/obrazek.jpg');">
Alternatywnym rozwiązaniem nie wymagającym angażowania programisty może być użycie wtyczki Autoptimize, które posiada możliwość lazy-loadingu działającego za pomocą JavaScript. Czytaj więcej o tej technice w artykule: Autoptimize – czy warto używać.

W obu przypadkach najrozsądniejszym jednak rozwiązaniem wydaje się przepisanie elementów tak aby w znacznikach img znajdował się atrybut loading. W przypadku elementów, które używają stylu background-image nadal możemy używać techniki lazy-loading jednak musimy dodać kilka linii JavaScript aby to zadziałało. Cały mechanizm tłumaczyłem w artykule: lazy-loading zdjęć. Jeżeli nie chcesz wykorzystywać opóźnionego ładowania dla tła, przepisz kod HTML bannera lub slajdera w taki sposób aby tło było obrazkiem. Wystarczy, że div otaczający obrazek i zawierający inne elementy, które powinny się znajdować na obrazku będzie miał następujący styl:
.banner-container{ position:relative; }
A sam obrazek i elementy, które mają się na nim znajdować (np. napisy lub przyciski do obsługi slajdera) będą miały ustawione wartości z-index rosnąco zgodnie z kolejnością patrząc od najniższej warstwy.
Ogranicz wpływ kodu spoza witryny – WordPress

Kod spoza witryny to wszelkie zasoby wpływające na ścieżkę krytyczną, które hostowane są na zewnętrznej domenie (czyli domenie różniącej się od głównej domeny witryny, którą optymalizujemy). Mogą to być pliki CSS/JS dołączane umyślnie przy tworzeniu motywu, kod dodany przez wtyczki oraz skrypty dołączane do celów analityki ruchu na stronie internetowej. Istnieją dwa rozwiązania tego problemu. Możemy po prostu przenieść zasoby na nasz serwer, lub wykluczyć zasoby ze ścieżki krytycznej za pomocą opóźniania. Skrypty CSS ładujemy po zdarzeniu onload a skrypty JavaScript można przenieść do osobnego pliku i załadować je asynchronicznie.
Pokażę to na przykładzie skryptu Google Analytics. Tworząc konto w tego typu narzędziach jesteśmy instruowani aby dodać jakiś kod do nagłówka lub stopki:
<!-- Google Analytics --> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-XXXXX-Y', 'auto'); ga('send', 'pageview'); </script> <!-- End Google Analytics -->
Ten kod zazwyczaj dodajemy do ciała strony internetowej, co jest nieprawidłowe z perspektywy optymalizacji. Jak czytamy w poradniku o optymalizacji JavaScript, które przygotowało samo Google: https://developers.google.com/speed/docs/insights/BlockingJS, ładowanie tego typu kodów służących analityce należy wykluczyć ze ścieżki krytycznej renderowania za pomocą async. Skoro użycie async jest możliwe tylko dla skryptów umieszczonych w osobnych plikach .js, kody związane z chatem, analityką i monitorowaniem odwiedzin należy dodać do takiego pliku, nazwać go np. analytics.js i dodać do stopki.
W WordPressie można tego dokonać za pomocą własnej wtyczki lub dodając taki kod do pliku functions.php (aktywnie wykorzystywanego motywu lub jeśli istnieje motywu potomnego):
function my_async_scripts() { echo '<script src="'.home_url().'/analytics.js" async></script>'; } add_action( 'wp_footer', 'my_async_scripts' );
Tę technikę wykorzystujemy wtedy, kiedy jakaś usługa każe nam dodać jakikolwiek kod JavaScript do naszej strony WordPress lub sklepu WooCommerce. Nieco inaczej musimy reagować kiedy kod spoza witryny dotyczy samego motywu lub którejś ze wtyczek. Należy skopiować zasób, który znajduje się na zewnętrznej domenie i umieścić go na własnym serwerze. Za pomocą wp_dequeue_style(), wp_deregister_style(), wp_dequeue_script() i wp_deregister_script() usuwamy styl / skrypt, który jest hostowany poza naszym serwerem (np. na CDN):
add_action( 'wp_print_scripts', 'optimize_scripts_psi', PHP_INT_MAX); function optimize_scripts_psi() { wp_dequeue_script('bootstrap'); wp_deregister_script('bootstrap'); }
Następnie dodajemy ten zasób posługując się plikiem znajdującym na naszym serwerze:
wp_enqueue_script( "bootstrap-optimized", get_template_directory_uri()."/js/bootstrap.js", array("jquery"),"1.1", true);
Co oznaczają parametry we wspomnianych funkcjach dokładnie wytłumaczyłem w artykule: Jak stworzyć motyw WordPress. Jeżeli te techniki nie zadziałają (bo skrypt jest zbyt ciężki, można odłożyć jego dodanie do strony dopiero po kilku sekundach po załadowaniu strony za pomocą techniki, którą zaprezentowałem w artykule: Jak optymalizować JavaScript).
Zmień rozmiar obrazów – WordPress

Wyświetlane na stronie obrazy, grafiki i zdjęcia powinny być dostępne w tych rozmiarach jakie akurat są potrzebne – nie mogą być zbyt małe, bo wówczas nie wykorzystujemy dostępnego pola roboczego przeglądarki (a rozciągnięte będą się wydawały mało wyraźne) ani zbyt duże, bo wówczas zwiększamy rozmiar danych jakie trzeba pobrać aby wyświetlić stronę.
Odpowiednie rozmiary obrazów definiuje się przy konstruowaniu szablonu a automatyczne skalowanie obrazów, które ma miejsce przy wysyłaniu obrazków do biblioteki mediów, odpowiada za to aby na stronie WordPress był wykorzystywany taki rozmiar jaki jest potrzebny. Działa to na podstawie zapytań medialnych w elemencie img samego obrazka. Jeżeli obrazy mają nieprawidłowe rozmiary, możemy dokonać edycji najważniejszych rozmiarów bezpośrednio w samym panelu:

Kolejną techniką jest zmiana lub dodanie rozmiarów w pliku functions.php lub za pomocą wtyczek. Służą do tego instrukcje add_image_size(). Przykład użycia:
add_image_size('hd-ready', 1280, 720);
Tak zdefiniowane rozmiary muszą być wykorzystane w samym szablonie. Np:
echo wp_get_attachment_image(get_the_ID(), "hd-ready", "", array("class" => "img-responsive"));
Podczas redagowania treści należy świadomie wybierać, czy zdjęcie ma mieć mały, średni lub duży rozmiar. Zdecydowanie warto unikać pełnego rozmiaru:

Jeżeli zatem dodanie rozmiarów nie przynosi efektów, oznacza to, że szablon lub narzędzia do edycji wyglądu ignorują dobre praktyki i nie wykorzystują w pełni potencjału WordPressa. Zdjęcia są prawdopodobnie zakodowane „na sztywno” wyciągając URL konkretnego rozmiaru lub oryginału i nie użyto wbudowanych w WordPressa funkcji do umieszczania różnych wariantów zdjęć w wielu rozmiarach.
Temat rozmiarów obrazów w WordPress jest złożony a wokół ich optymalizacji narosło wiele mitów. Na pewno nie musisz zmniejszać rozmiarów zdjęć przed załadowaniem ich na stronę – to strata czasu bo WordPress i tak dokonuje ponownej konwersji na zdefiniowane w szablonie i w ustawieniach WordPress rozmiary. W przypadku zbyt małego obrazka istnieje ryzyko pogorszenia doświadczeń użytkowników korzystających z wysokiej jakości monitora lub wysokiej klasy telefonu. Zachęcam do przeczytania osobnego artykułu Optymalizacja obrazów WordPress. W tym wpisie dokładnie tłumaczę dlaczego posiadanie różnych rozmiarów jest istotne dla optymalizacji obrazów i dlaczego warto dodawać duże zdjęcia wysokiej jakości bezpośrednio do biblioteki WordPressa.
Użyj efektywnego kodowania obrazów – WordPress

Wysyłane do biblioteki WordPress obrazy i zdjęcia są konwertowane na mniejsze rozmiary tzw. miniaturki. W przypadku zdjęć zapisanych w stratnych formatach zapisu takich jak .jpg i innych odpowiednikach nowej generacji konwersja odbywa się z pewną dokładnością. Domyślnie jest to ok 80% bo wartość ta uznawana jest za dobry kompromis pomiędzy jakością zdjęcia a rozmiarem pliku.
W WordPressie można ustalić jaki ma być współczynnik jakości przy kodowaniu. WordPress udostępnia filtr do zmiany wartości tego współczynnika:
add_filter('jpeg_quality', function($arg){return 80;});
Jak można się domyślić, w przypadku pojawienia się tej uwagi w PageSpeed wartość tego współczynnika na danej stronie jest z jakichś powodów zwiększona i należy tę wartość obniżyć. W przypadku korzystania wtyczek, które automatycznie generują rozmiary w formatach nowej generacji ustawień powinniśmy dokonać w samej wtyczce:

Użyj formatów wideo dla animacji – WordPress

Format .gif już wiele lat temu pozwalał wstawiać proste animacje do stron internetowych. Formatu tego już się jednak nie używa ze względu na wiele wad w stosunku do nowocześniejszych alternatyw takich jak animacje SVG oraz typowe formaty wideo MPEG4/WebM. Warto rozważyć rezygnację z animacji w postaci plików graficznych jeżeli nie pełnią bardzo istotnej roli lub konwersję statycznych plików zapisanych w formacie GIF na efektywniejsze formaty PNG/WebP. Jeżeli używaliśmy formatu GIF w treści postów i jest ich bardzo dużo można wykorzystać wtyczkę do masowej konwersji tak jak robiliśmy to w przypadku plików WebP.
GIF nie zapewnia odpowiedniej jakości wizualnej, a zakodowana w nim grafika zajmuję dużo więcej miejsca. W Przypadku długich animacji format wideo jest w stanie wyświetlić początkowe klatki bez pobierania całego pliku. GIF zaś nie zapewnia takiej funkcjonalności.
Ogranicz nieużywany kod CSS – WordPress

Kod CSS odpowiada za to jak wyglądają elementy HTML wygenerowane przez CMS WordPress. Nieużywany kod CSS w pewnym stopniu jest czymś naturalnym, ponieważ rzadko zdarza się sytuacja, że wszystkie elementy HTML występują na wszystkich podstronach. Przykładowo: styl formularza kontaktowego jest używany na stronie kontakt, mimo to aby nie komplikować budowy strony styl jest ładowany do wszystkich podstron. Z taką sytuacją mamy do czynienia praktycznie z wszystkimi stylami CSS w WordPressie.
Błąd o nieużywanym kodzie CSS pojawia się w PageSpeed dopiero wtedy, kiedy takiego kodu jest zbyt dużo. 5% lub 10% nadmiaru nieużywanego kodu nie jest szkodliwy z perspektywy szybkości działania strony a PageSpeed nie zgłosi błędu natomiast kiedy nieużywanych instrukcji jest bardzo dużo, np. 85% to mamy do czynienia z sytuacją patologiczną. Ilość nadmiarowego kodu CSS w WordPressie można sprawdzić za pomocą przeglądarki Chrome. Narzędzie Coverage pokazuje ile instrukcji zostało wykorzystanych a ile odnosi się do elementów, które na bieżącej stronie nie wystąpiły.

Instrukcję o tym jak wyświetlić ten panel i jak należy badać poszczególne podstrony witryny opisałem w artykule: Jak usunąć nieużywany kod CSS. Jeżeli PageSpeed wykryje, że testujemy stronę WordPress podpowie nam, że mamy usunąć wtyczki lub poszukać zamiennika, który nie dodaje tylu CSSów do strony. Oczywiście, w praktyce nie zawsze jest to możliwe. Usunięcie to de facto nie jedyna metoda ograniczenia kodu i jego wpływu na wydajność strony WordPress. PageSpeed doradza, że taki kod także opóźnić – problem polega na tym, że nawet narzędzie do badania zasięgu kodu nie jest w stanie przewidzieć wszystkich sytuacji jakie mogą wystąpić na stronie (np. pojawienie się konkretnego pop-upu po wykonaniu przewidzianej akcji przez użytkownika). Kiedy już zidentyfikujemy style CSS, które można usunąć lub ograniczyć robimy to za pomocą poznanych funkcji:
add_action( 'wp_print_styles', 'optimize_styles_psi', PHP_INT_MAX ); function optimize_styles_psi() { wp_dequeue_style('livechat'); wp_deregister_style('livechat'); }
Narzędzie do badania zasięgu kodu pokaże nam, które konkretnie instrukcje został użyte, a które nie:

Nieużywane instrukcje usuwany lub przekopiowujemy do innego pliku pamiętając aby w obu plikach zachować logiczną strukturę zapytań medialnych! Zmodyfikowany styl z ograniczoną ilością kodu CSS możemy załączyć do strony za pomocą:
wp_enqueue_style( "livechat-optimized", get_template_directory_uri()."/css/livechat-opitmized.css",false,'1.1','all');
Ten plik zawiera instrukcje zaznaczone na zielono przez narzędzie do badania zasięgu kodu Coverage. Instrukcje, które zostały zaznaczone na czerwono – czyli te, które nie zostały użyte od razu po załadowaniu strony możemy po prostu usunąć (zapisując sobie ich kopię gdyby w przyszłości się okazało, że zawierały użyteczne instrukcje) lub załadować do strony WordPress z opóźnieniem.
Do dołączania styli opóźnionych niestety nie możemy wykorzystać natywnej instrukcji WordPress wp_enqueue_style(), ponieważ WordPress nie obsługuje tak zaawansowanych technik optymalizacji wydajności (nie pozwoli nam dodać atrybutu onload) i odpowiednią linię dołączającą kod CSS musimy wstawić niemal ręcznie:
add_action( 'wp_head', 'header_styles_psi', PHP_INT_MAX ); function header_styles_psi(){ ?> <link rel="stylesheet" href="<?php echo get_template_directory_uri(); ?>/assets/css/livechat-lazy.css" media="screen" onload="if(media!='all')media='all'"> <?php }
Istnieje jeszcze jeden sposób optymalizacji polegający na tym, że ładujemy konkretny styl tylko na wybranych podstronach. Bardzo łatwo można osiągnąć taki cel otaczając funkcję wp_enqueue_style() instrukcją if, w której korzystamy z funkcji is_page(), is_single(), is_front_page(); Poniższy przykład pokazuje jak załadować konkretny styl tylko na stronie kontakt:
if (is_page("kontakt")){ wp_enqueue_style( "livechat-optimized", get_template_directory_uri()."/css/livechat-opitmized.css",false,'1.1','all'); }
Zmniejszenie objętości kodu CSS jest możliwe za pomocą bardzo prostej techniki optymalizacyjnej o nazwie minifikacja. Polega ona na usunięciu znaków nie wpływających na interpretację arkuszy, które programista dodał dla własnej wygody np. nadmiarowe spacje, znaki nowej linii i tabulatory. Kod CSS można przerobić własnoręcznie i załadować na serwer aby nie obciążać go dodatkowymi procesami, które musi co jakiś czas wykonywać bezpośrednio przy odwiedzaniu strony internetowej. Ostatecznie można wykorzystać wtyczkę do minifikacji CSS w WordPressie, jedną z nich jest Autoptimize.

Ogranicz nieużywany JavaScript – WordPress

Kod napisany w JavaScript może pełnić wiele funkcji na stronie internetowej WordPress. Może odpowiadać za działanie slajdera lub zatwierdzać przesyłanie formularza bez odświeżenia strony. Podobnie jak style, JavaScript może się odnosić do elementów występujących na wybranych podstronach lub realizować pewne funkcje dopiero po wykonaniu konkretnej akcji np. podczas wysyłania formularza. Niektóre motywy mogą dołączać skrypty JS, które w ogóle nie są używane – dzieje się tak, kiedy nie wykorzystujemy wszystkich funkcjonalności jakie dostarcza motyw.
Zazwyczaj jest tak, że wszystkie skrypty JavaScript z jakich korzysta strona są ładowane na wszystkich podstronach witryny. Możemy zatem wykorzystać wiele technik, które stosowaliśmy przy okazji stylów CSS. Skrypty JavaScript też można badać pod kątem zasięgu kodu. Służy do tego funkcja Coverage w przeglądarce Chrome. Audyt ten jest w stanie zweryfikować czy konkretny blok kodu JS jest wykorzystywany czy nie.
Skrypt JavaScript możemy usunąć za pomocą funkcji wp_dequeue_script():
add_action( 'wp_print_scripts', 'optimize_scripts_psi', PHP_INT_MAX); function optimize_scripts_psi() { wp_dequeue_script('contact-form-validator'); }
Odchudzony plik możemy następnie załadować za pomocą funkcji enqueue_script():
wp_enqueue_script( "contact-form-validator-optimized", get_template_directory_uri()."/js/contact-form-validator-optimized.js", "","1.1", true);
Ograniczenie kodu JS jest też możliwe za pomocą bardzo prostych technik polegających na usunięciu białych znaków co fachowo określamy jako minimalizację lub minifikację kodu JavaScipt. Proces można skutecznie zautomatyzować za pomocą takich wtyczek jak Autoptimize:

Osobiście preferuję dołączać już zminimalizowane pliki JS w paczce, która jest przeznaczona do wykorzystania na produkcji. Odciążam w ten sposób serwer z ciągłego wykonywania tej operacji, która co jakiś czas jest ponawiana np. po czyszczeniu pamięci cache.
Wyeliminuj zasoby blokujące renderowanie – WordPress

Odchudzanie stylów i skryptów, które poruszono w poprzednich punktach można wykonywać do pewnego momentu. Ostatecznie okazuje się, że każdy plik ze stylem lub skryptem CSS blokuje renderowanie strony internetowej. Problem jest tym większy im więcej ważą pliki z tymi zasobami oraz ich ilości. Istnieje wiele technik, które pozwalają zminimalizować wpływ stylów i skryptów na blokowanie krytycznej ścieżki renderowania.
Blokujący CSS w WordPressie
Jedną z nich jest wydzielenie krytycznego kodu CSS, które podpowiada samo narzędzie PageSpeed Insights. Krytyczny kod CSS to te same instrukcje które zaznaczył na zielono test Coverage zakładając, że nie przewijaliśmy okna roboczego przeglądarki czyli tzw. pola widoku (ang. viewport). Krytyczny kod CSS pozwala na szybkie załadowanie się obszaru above the fold czyli tego „górnego” obszaru strony, który widać w przeglądarce na samym początku. Istnieją też narzędzia online do generowania krytycznego kodu CSS oraz narzędzia dla programistów w postaci modułu npm oraz wtyczki do webpacka.
W ekosystemie WordPress istnieje kilka wtyczek ułatwiających umieszczenie kodu krytycznego są nimi Autoptimize:

Kod krytyczny możemy wygenerować za darmo za pomocą wcześniej wspomnianych narzędzi, serwisów online lub płatnego rozszerzenia o nazwie Critical CSS:

Trudność w generowaniu kodu CSS polega na tym że jest on często nieco inny na poszczególnych podstronach. Każdy typ podstrony WordPress (strona główna, kategoria, pojedynczy wpis) wymaga zazwyczaj nieco innego kodu krytycznego. Muszę wspomnieć, że generowanie kodu krytycznego przez takie narzędzia nie jest niezawodne i nie zawsze jest ono skuteczne. Niepełny kod krytyczny może podwyższać wskaźnik CLS i znacznie pogorszyć doświadczenia użytkowników.
Wygenerowany samodzielnie kod CSS można dodać posługując się akcją wp_head. Jeżeli chcemy załączyć różny kod na różnych typach podstron pamiętajmy o użyciu instrukcji if z funkcjami is_page() :
add_action( 'wp_head', 'my_critical_css', PHP_INT_MAX ); function my_critical_css(){ if( is_page() ){ ?> <style> /* Krytyczny kod CSS */ </style> <?php } }
Opóźnianie kodu CSS i JS poruszane w poprzednich punktach też może rozwiązać problem blokowania renderowania jeżeli zdecydowaliśmy się opóźnić CSS lub załadować instrukcje JavaScript asynchronicznie:
add_action( 'wp_print_scripts', 'optimize_scripts_psi', PHP_INT_MAX); function optimize_scripts_psi() { wp_dequeue_script('nazwa-skryptu'); } add_action( 'wp_footer', 'my_async_scripts' ); function my_async_scripts() { echo '<script src="'.home_url().'/skrypt-zoptymalizowany.js" async></script>'; }
W przypadku stosunkowo dużych plików JavaScript, narzędzie PageSpeed Insights może nadal zgłaszać ten problem mimo wykorzystania asynchronicznego ładowania. W ostateczności można użyć ładowania ze stałym opóźnieniem od załadowania się strony, np. 5 sekundowym:
function loadJs(url){ var script=document.createElement('script');script.src=url; script.setAttribute('async','true'); document.documentElement.firstChild.appendChild(script); } document.addEventListener('DOMContentLoaded', function() { setTimeout(function(){ loadJs(<?php echo get_template_directory_uri(); ?>/js/live-chat.js"); },5000); }
W ten sposób możemy opóźniać ładowanie skryptów, które nie są kluczowe przy ładowaniu się strony WordPress. Technika ta dobrze się sprawdza przy wszelkiego rodzaju widżetach i zewnętrznych usługach typu live-chat, wyświetlanie opinii i innych integracji o podobnym działaniu. Wówczas bardzo trudno zmodyfikować oryginalny kod jaki dostarcza usługodawca lub jest on zamieszczony w zewnętrznej lokalizacji.
Blokujący JavaScript w WordPressie
Skrypty zamieszczone w tagach <script> nie mogą być przechowywane w pamięci podręcznej przeglądarki a dodatkowo nie można nadać im atrybutu async. Każdy kod powinien być umieszczony w osobnym pliku a odniesienie do niego w stopce (o ile jest to możliwe i kiedy inne pliki nie są zależne od tego pliku) powinno posiadać atrybut async.
Skróć wstępny czas reakcji serwera – WordPress

Ten punkt ma najistotniejszy wpływ na wskaźnik FID (First Input Delay). Wstępny czas reakcji serwera to nic innego jak TTFB głównego dokumentu HTML. Zakładając że nie ograniczamy funkcjonalności witryny, czas reakcji serwera całkowicie zależy od jego wydajności. W niektórych przypadkach może pomóc pamięć podręczna (Cache), która zapisuje generowany przez WordPressa kod HTML do pliku tekstowego. Technika ta niestety nie działa na stronach z wieloma polami dynamicznymi np. w sklepach internetowych z koszykiem lub w trakcie kiedy klient jest zalogowany w serwisie. Warto zwrócić uwagę, że w czasie kiedy Cache nie może działać CrUX nadal zbiera dane o szybkości.

Wtyczki do cache takie jak WP Super Cache lub W3 Total Cache pomogą radykalnie skrócić czas reakcji serwera jeżeli w naszym serwisie przeważają podstrony zawierające statyczne treści. Czytaj więcej co to jest TTFB i jak go obniżyć.
Na konkretnych stronach dynamicznych (gdzie standardowy cache strony nie może zadziałać) skutecznym rozwiązaniem może być wyłączenie wybranych wtyczek. Jest to możliwe jeżeli stworzymy must-use plugin z takim kodem:
add_filter( 'option_active_plugins', 'disable_plugin_psi' ); function disable_plugin_psi( $plugins ){ if(strpos($_SERVER['REQUEST_URI'], '/kontakt/') === FALSE && !is_admin() ) { $key = array_search( 'contact-form-7/wp-contact-form-7.php' , $plugins ); if ( false !== $key ) unset( $plugins[$key] ); } return $plugins; }
Kod taki zapisujemy w folderze /wp-contents/mu-plugins/ nadając mu przykładowo nazwę plugin-psi-optimizer.php. W tym przykładzie kod wyłącza Contact Form 7 na każdej stronie, która nie jest stroną „kontakt”. Działanie takie można wykonać bez programowania za pomocą wtyczki Plugin Organizer, którą stworzył Jeff Sterup bądź podobnej. Oczywiście tego typu działania optymalizacyjne będą działać do pewnego momentu a w przypadku niektórych witryn i wtyczek ich wykorzystanie może być niemożliwe. Pamiętaj, że zawsze lepiej jest dysponować hostingiem z większą mocą procesora i z kompatybilnymi serwerami wspomnianymi w dokumentacji WordPressa czyli Apache / NGINX.
Wyświetlaj zasoby statyczne, stosując efektywne zasady pamięci podręcznej – WordPress

Przeglądarka internetowa analizując kod HTML i renderując dokument HTML pobiera wiele zasobów statycznych, które są potrzebne do wyświetlenia się konkretnej strony internetowej. Do zasobów statycznych zaliczamy zdjęcia, pliki CSS, pliki JS a także pliki SVG zapisane w odrębnych plikach. W przypadku WordPressa, wiele podstron korzysta z identycznych zasobów i przy przeglądaniu podstron konkretnej witryny nie musi ona pobierać tych wszystkich zasobów od nowa. Serwer jest w stanie oznaczyć pliki specjalnymi nagłówkami aby zapisywały się one w pamięci lokalnej przeglądarki i były tam przechowywane przez pewien okres czasu. Służą do tego nagłówki Expires i Cache-Control.
Poprawnie skonfigurowany hosting oraz hosting WordPress powinien już domyślnie ustawiać takie nagłówki. Narzędzie PageSpeed zaleca aby ustawić je na okres 365 dni. Nie jest prawdą, że tak długi czas przechowywania plików spowoduje jakiekolwiek problemy np. z aktualizacją serwisu. WordPress ma specjalne mechanizmy aby zmodyfikowane zasoby pobierały się od nowa, służą do tego automatycznie generowane query-stringi a pliki statyczne można potraktować tzw. inwalidacją.
Zasady pamięci podręcznej w przypadku serwerów Apache
W serwerach Apache odpowiedniego dostrojenia nagłówków można dokonać w plikach konfiguracyjnych znajdujących się w folderze /etc/apache2/sites-enabled lub w pliku .htaccess:
ExpiresActive On ExpiresDefault "access plus 1 year" # Zdjęcia ExpiresByType image/jpg "access plus 1 year" ExpiresByType image/jpeg "access plus 1 year" ExpiresByType image/png "access plus 1 year" ExpiresByType image/gif "access plus 1 year" ExpiresByType image/svg+xml "access 1 year" ExpiresByType image/webp "access 1 year" # Zasoby tekstowe ExpiresByType text/css "access plus 1 year" ExpiresByType text/javascript "access plus 1 year" ExpiresByType text/html "access plus 1 year" ExpiresByType application/xhtml+xml "access plus 1 year" ExpiresByType application/javascript "access plus 1 year" ExpiresByType application/x-javascript "access plus 1 year" # Multimedia ExpiresByType audio/ogg "access 1 year" ExpiresByType video/mp4 "access 1 year" ExpiresByType video/ogg "access 1 year" ExpiresByType video/webm "access 1 year"
Zasady pamięci podręcznej w przypadku serwerów nginx
Na serwerach nginx przechodzimy do plików konfiguracyjnych znajdujących się w /etc/nginx/sites-available i konfiguracja przykładowej strony może wyglądać tak:
server { listen 80; server_name jakas-strona.pl; access_log /location/of/access.log; error_log /location/of/error.log; location / { root /location/of/www; index index.html index.htm; if ($request_uri ~* ".(ico|css|js|gif|jpe?g|png)$") { expires 365d; access_log off; add_header Pragma public; add_header Cache-Control "public"; break; } } }
Czytaj więcej o instrukcjach Expires i Cache-Control i jakie są pomiędzy nimi różnice.
Zapewnij widoczność tekstu podczas ładowania czcionek internetowych – WordPress

Podczas ładowania kodu HTML przeglądarka jest w stanie wyświetlić jej najważniejsze fragmenty nawet wtedy kiedy kod nie jest w pełni przeanalizowany. To dlatego wydzielenie kodu krytycznego tak radykalnie przyspiesza pojawienie się obszaru above the fold. Wytłumaczyliśmy już, że zasoby statyczne ładują się z pewnym opóźnieniem. W przypadku wyświetlania się tekstu – zazwyczaj kluczowego elementu, który stanowi LCP na stronie internetowej – bardzo istotne jest szybkie pobranie fontu i wyrenderowanie tekstu w odpowiednim miejscu wielkości i stylu. Niestety, bardzo szybkie załadowanie się pliku z fontami, które ważą od kilkudziesięciu do kilkuset kilobajtów nie zawsze jest możliwe. Z tego powodu do standardu CSS dodano instrukcję font-display. To za pomocą tego rozwiązania można określić czy teksty mają się najpierw pojawić w domyślnych fontach po czym są one zamieniane na właściwy niestadardowy font bądź przeglądarka ma poczekać na załadowanie się fontu.
Dla elementów LCP warto ustawić wartość swap, która powoduje wyświetlenie się tekstu w domyślnej – najczęściej zbliżonej stylistycznie czcionce. niektóre motywy WordPress korzystają z serwisu Google Fonts. Za pomocą poznanej nam funkcji wp_dequeue_style() można taki font usunąć i dodać styl z zadeklarowaną wartością font-display:
add_action( 'wp_print_styles', 'optimize_styles_psi', PHP_INT_MAX ); function optimize_styles_psi() { wp_dequeue_style('google-fonts'); }
Następnie dodajemy font z dodatkowym parametrem swap. To spowoduje że serwis Google fonts wygeneruje nam styl ze stylem font-display:swap:
function google_fonts_psi() { wp_enqueue_style( 'google-fonts-psi', 'https://fonts.googleapis.com/css2?family=Open+Sans+Condensed:wght@300&family=Roboto:wght@300&display=swap', flase ); } add_action( 'wp_enqueue_scripts', 'google_fonts_psi' );
W punkcie o ograniczaniu wpływu kodu spoza witryny powiedzieliśmy, że należy unikać ładowania zasobów z zewnętrznych zasobów, dlatego korzystne może być skopiowanie pliku na nasz serwer. W punkcie „załaduj wstępnie kluczowe żądania” powiedzieliśmy, że takie zasoby można ładować wstępnie (ang. preload) lub dołączyć jako krytyczny CSS. Style CSS dotyczące fontów i obszaru above-the-fold zazwyczaj są krytycznym CSSem dlatego w praktyce styl CSS jaki generuje Google Fonts wyciąga się i dołącza w tagach <style> jako krytyczny kod CSS:
add_action( 'wp_head', 'header_styles_psi', PHP_INT_MAX ); function header_styles_psi(){ ?> <style> /* cyrillic-ext */ @font-face { font-family: 'Open Sans Condensed';... </style> <?php }
W przypadku najprostszych technik opisywanych na początku tego punktu pomocnym narzędziem może się okazać Autoptimize. Wtyczka ta pozwala nam hurtowo dodać font-display do używanych stylów.

W przypadku dodawania font-display:swap; należy zwrócić szczególną ostrożność na wskaźnik CLS. Korzystając z właściwości font-display z wartością swap konieczne może się okazać dodatkowe stylowanie strony aby strona nie „skakała” przy podmianie fontów. Czytaj więcej o szczegółowych technikach optymalizacji czcionek internetowych na stronach internetowych.
Unikaj zbyt dużego DOM – WordPress

Duży DOM to porostu zbyt złożony i skomplikowany front-end strony internetowej. Porady związane z tym problemem dotyczą najczęściej zmniejszenia ilości sekcji czy usunięcia widgetów – one jednak nie rozwiązują problemu a prowadzą do jego ominięcia. Prawidłowym rozwiązaniem problemu zbyt dużego DOM to przepisanie HTMLu strony internetowej tak aby kod HTML był mniej zagnieżdżony i składał się z mniejszej ilości elementów. Dobre rezultaty może dać także zastosowanie lazy-loadingu całych sekcji tak jak w przypadku infinite-scroll.
Inne techniki optymalizacji poprawiające Core Web Vitals
Należy pamiętać, że w przypadku podstawowych wskaźników internetowych takich jak LCP i FID, każde działanie zmierzające do szybszego wczytania się zasobów jest w stanie je poprawić. Z tego powodu coraz większą popularnością cieszą się techniki CDN całej strony za pośrednictwem Reverse Proxy oraz Offloadingu zasobów statycznych na CDN. Czytaj więcej w artykułach:
Optymalizacja WooCommerce
Sklepy WooCommerce posiada kilka specyficznych cech, które powodują, że przy optymalizowaniu możemy zwrócić uwagę na konkretne zasoby i wybrać trafniejsze techniki radzenia sobie z częstymi problemami. Niektóre style i skrypty są potrzebne wyłącznie na stronie z produktem. Do takich zasobów można zaliczyć wszystko to co odpowiada za funkcjonowanie galerii produktu czy wtyczek, które funkcjonują tylko w ramach strony produktowej. Można wtedy wykorzystać metodę wp_dequeue_style() oraz wp_dequeue_script() w instrukcji warunkowej:
if( !is_product ){
wp_dequeue_style( 'better-wc-gallery' );
}
Niektóre funkcjonalności działają tylko wtedy kiedy klient jest zalogowany do sklepu. Taka sytuacja może występować w przypadku niestandardowych panelów klienta i możemy wykorzystać ten fakt na korzyść szybkości działania sklepu z perspektywy użytkowników niezalogowanych i robotów Google. Wystarczy użyć funkcji is_user_logged_in() i wykorzystać ją tak jak pokazałem w poprzednim przykładzie.
W przypadku sklepów z synchronicznym koszykiem zakupów lub takich, które z jakichś powodów wymagają logowania należy pamiętać, że wówczas nie działa standardowy mechanizm pamięci podręcznej stron. Trzeba wtedy skupić się na wyeliminowaniu wąskich gardeł, które powodują długi czas odpowiedzi.
Podsumowanie
Optymalizacja strony WordPress pod kątem Core Web Vitals i PageSpeed to trywialne zadanie jeżeli rozumiemy problem i znamy podstawy programowania w środowisku WordPress. Wyeliminowanie z kodu blokujących stylów CSS i skryptów JavaScript oraz ich opóźnianie daje ogromną korzyść, która realnie przyspiesza ładowanie się strony oraz radykalnie poprawia wskaźniki LCP i FID. Odchudzanie CSS / JS oraz wydzielanie kodu krytycznego to trzeba przyznać żmudne działania, które wymagają cierpliwości ale też pewnego doświadczenia. Nie zapominajmy o zdjęciach, których optymalizowanie jest łatwe z definicji ale może być kłopotliwe w środowisku WordPress. Poprawna optymalizacja grafik i materiałów wideo często ma pozytywny efekt w postaci zadowalającej wartości CLS. Popularne techniki optymalizowania strony WordPress, o których możesz przeczytać na wielu innych blogach polegające na minimalizowaniu zasobów tekstowych czy stosowaniu wszelkiego rodzaju sieci CDN oczywiście też dadzą pozytywne efekty ale to są działania drugo a nawet trzeciorzędne.
Odpowiedz lub skomentuj