Jak uzyskać 100/100 punktów w Google PageSpeed Insights

Google PageSpeed Insights

Google PageSpeed Insights to narzędzie, które dla wielu osób jest (często jedynym słusznym) wyznacznikiem jakości i szybkości działania strony internetowej. Nie jest to do końca prawda, ale faktem jest, że przedstawiany na stupunktowej skali wynik daje obraz tego, jak szybka jest nasza strona i co można zrobić, aby była szybsza.

Maksymalny wynik 100 punktów w teście PageSpeed Insights to marzenie niejednego właściciela serwisu internetowego. I mimo że jest to tylko „sztuka dla sztuki”, to w tym wpisie na konkretnym przykładzie pokażę, jak można taki wynik osiągnąć.

Wynik testu PageSpeed Insights zależy od bardzo wielu czynników, z których większość omawiam w tym wpisie. Nie gwarantuję jednak, że wykonanie wszystkich opisanych tu czynności odniesie dokładnie taki sam skutek w każdym przypadku i będzie wystarczające do uzyskania podobnego wyniku.

Czym jest PageSpeed Insights?

PageSpeed Insights to stworzone przez firmę Google narzędzie do mierzenia wydajności stron internetowych. Bada ono każdą stronę dwukrotnie: pod kątem urządzeń mobilnych (mobile) i pod kątem „zwykłych” komputerów (desktop). Wynik obu tych testów jest przedstawiany na 100-punktowej skali – im wyższy wynik, tym lepiej.

Badanie wydajności jest wykonywane za pomocą zestawu specjalnych reguł. Niektóre z nich są ważniejsze od innych, przez co ich spełnienie daje naszej stronie więcej punktów. Mimo że wspomniane reguły są dość dobrze opisane w dokumentacji narzędzia, to nie wszyscy wiedzą co należy zrobić, aby daną regułę spełnić.

Raport, jaki otrzymujemy wraz z liczbowym wynikiem testu, pokazuje reguły, które są przestrzegane na naszej stronie oraz listę problemów, które na niej występują (nieprzestrzegane reguły). Czerwonym wykrzyknikiem oznaczono najistotniejsze problemy, których usunięcie może mieć duży wpływ na szybkość naszej strony (a więc i na wynik testu). Żółty wykrzyknik oznacza problemy, które warto usunąć – nie spodziewajmy się po nich wielkiego skoku wyniku testu, ale jeśli chcemy wycisnąć komplet punktów, to i nimi powinniśmy się zająć.

Warto dodać, że PageSpeed Insights nie bierze pod uwagę aspektów działania strony, które są zależne od wydajności sieci, głównie dlatego, że praktycznie nigdy nie jest ona stała. Brane są natomiast pod uwagę takie czynniki, jak konfiguracja i wydajność serwera, na którym działa nasza strona, struktura kodu HTML oraz sposób, w jaki strona korzysta z zasobów zewnętrznych, takich jak pliki graficzne, skrypty JavaScript czy arkusze stylów CSS.

Więcej informacji na temat PageSpeed Insights znaleźć można w oficjalnej dokumentacji.

Jaki wynik PageSpeed Insights jest dobry?

Stronę można uznać za działającą dobrze, gdy w obu testach osiągnie co najmniej 85 punktów. Wbrew pozorom nie jest to wynik trudny do osiągnięcia. Test dla urządzeń mobilnych jest nieco bardziej wymagający, tak więc zwykle to właśnie w nim ciężej jest osiągnąć dobry wynik.

Przygotowanie strony testowej

Ponieważ wpis ten chciałem oprzeć na konkretnym przykładzie, stworzyłem (oczywiście korzystając z WordPressa) stronę testową pagespeed.wpzen.pl, na której wykonywałem wszystkie modyfikacje. Można więc samemu sprawdzić, czy rzeczywiście osiąga ona wynik 100 punktów w obu testach (dla urządzeń mobilnych i komputerów).

Jeśli wynik będzie niższy niż 100 punktów, to prawdopodobnie wystąpił problem z czasem odpowiedzi serwera (tak to niestety na tym serwerze bywa). W takim przypadku wystarczy odczekać 30 sekund i wykonać test ponownie.

Testy wykonywałem tylko dla strony głównej serwisu. Większość z wykonanych przeze mnie działań będzie miała oczywiście pozytywny wpływ również na podstrony, ale może się zdarzyć, że optymalizacja poszczególnych typów podstron będzie wymagać dodatkowych zabiegów. Kilka zdań na ten temat napisałem w podsumowaniu, które znajduje się na końcu wpisu.

Prace zacząłem od instalacji najnowszej wersji WordPressa (w chwili pisania tego wpisu była nią wersja 4.4.2) i na aktywowaniu najnowszej wersji aktualnego domyślnego motywu Twenty Sixteen. Aby strona nie była pusta, zaimportowałem oficjalne dane testowe wraz z obrazkami – nie są one idealne, ale lepszych w tej chwili chyba nie ma.

Pora na pierwszy test narzędziem PageSpeed Insights. Wynik zaskoczył mnie nieco – pozytywnie, bo wcale nie był taki zły. 71 punktów w teście dla urządzeń mobilnych i 83 punkty w teście dla komputerów.

PageSpeed Insights

Oczywiście nikt nie kończy w tym miejscu budowy swojej strony – zawsze instalowane są dodatkowe wtyczki, które często dokładają własne skrypty JavaScript i arkusze stylów CSS, a czasem także kod HTML. Zainstalowałem więc następujące rozszerzenia:

  • Yoast SEO – popularna wtyczka wspomagająca optymalizację stron pod kątem SEO
  • Google Analytics by Yoast – wtyczka ułatwiająca instalację i konfigurację kodów śledzących dla Google Analytics
  • Contact Form 7 – rozszerzenie pozwalające na tworzenie formularzy; stworzyłem jeden formularz, który umieściłem w panelu bocznym
  • WP Retina – wtyczka dodająca obsługę ekranów Retina do zdjęć wstawianych do wpisów
  • Jetpack – znany kombajn z wieloma modułami (aktywowane najpopularniejsze moduły: Carousel, Custom CSS, Enhanced Distribution, Extra Sidebar Widgets, Omnisearch, Protect, Publicize, Related Posts, Sharing, Tiled Galleries i Widget Visibility)

Do pierwszego wpisu wstawiłem dodatkowo film z serwisu YouTube w taki sposób, aby był widoczny na stronie głównej mojego testowego serwisu. Za chwilę wyjaśnię dlaczego to zrobiłem.

PageSpeed Insights

Jak widać, wynik znacznie się pogorszył – 58 punktów w wersji mobilnej i 74 punkty w wersji desktopowej. To już jest coś, nad czym można pracować. Stwierdziłem, że taki stan strony jest wystarczający i uznałem go za punkt wyjściowy do optymalizacji pod kątem uzyskania jak najlepszego wyniku w teście PageSpeed Insights.

Optymalizacja strony

Po wykonaniu testu PageSpeed Insights należy odczekać 30 sekund przed wykonaniem kolejnego.

Skróć czas odpowiedzi serwera

Na pierwszy ogień wybrałem regułę, która jest stosunkowo łatwa do spełnienia – najczęściej wystarczy skorzystać z wtyczki cache. Ja (jak praktycznie zawsze) wybrałem WP Super Cache i skonfigurowałem ją zgodnie z własnym poradnikiem. Zgodnie z moimi oczekiwaniami, reguła została spełniona i zniknęła z listy „Warto poprawić”, ale wynik poprawił się o zaledwie jeden punkt.

Wykorzystaj pamięć podręczną przeglądarki

Ta reguła oznaczona jest jako bardzo ważna dla urządzeń mobilnych. Rzecz polega na ustawieniu odpowiednich nagłówków HTTP dla plików (`Expires`), które powinny być trzymane przez dłuższy czas w cache przeglądarki użytkownika. Niektóre wtyczki cache (np. W3 Total Cache czy Zencache) posiadają wbudowaną odpowiednią funkcję, którą wystarczy po prostu włączyć. Poza tym większość firm hostingowych domyślnie ustawia odpowiednie nagłówki, tak więc nie musimy się w ogóle o to martwić.

Najprostszą metodą na dodanie nagłówków `Expires` jest dodanie do pliku `.htaccess` następującego kodu:

<IfModule mod_expires.c>
	ExpiresActive On
	ExpiresDefault "access plus 1 month"
	ExpiresByType text/html "access plus 1 seconds"
	ExpiresByType image/gif "access plus 30 days"
	ExpiresByType image/jpeg "access plus 30 days"
	ExpiresByType image/png "access plus 30 days"
	ExpiresByType image/jpg "access plus 30 days"
	ExpiresByType image/svg+xml "access plus 30 days"
	ExpiresByType text/css "access plus 30 days"
	ExpiresByType text/javascript "access plus 30 days"
	ExpiresByType application/javascript "access plus 30 days"
	ExpiresByType application/x-javascript "access plus 30 days"
	ExpiresByType text/xml "access plus 60 minutes"
</IfModule>

Dodanie nagłówków `Expires` poprawiło wynik PageSpeed Insights o jeden punkt w teście dla urządzeń mobilnych i o dwa punkty w teście dla komputerów.

Jednak żeby nie było zbyt pięknie, na liście zasobów, które nie mają odpowiednich nagłówków lub mają ustawiony zbyt krótki „czas życia”, pozostało kilka pozycji:

PageSpeed Insights

Trzy pierwsze to pliki z serwisu Gravatar, czwarty to skrypt zarządzający reklamami w filmach z YouTube, a ostatni to znany wszystkim skrypt Google Analytics. Co możemy z tym zrobić, skoro wszystkie te pliki znajdują się na zewnętrznych serwerach i nie mamy żadnego wpływu na ich nagłówki?

Zacznijmy od Gravatara. Możemy oczywiście wyłączyć obsługę awatarów z tego serwisu, ale nie tędy droga. Najlepszym rozwiązaniem jest pobieranie awatarów na nasz serwer, dzięki czemu zostaną do nich dodane takie nagłówki, jak do wszystkich innych plików graficznych. Oczywiście nie będziemy robić tego ręcznie – z pomocą przyjdzie nam wtyczka Harrys Gravatar Cache, która automatycznie zapisze na naszym serwerze wszystkie awatary i podmieni odpowiednie adresy URL plików. Rozszerzenie ma kilka opcji (Ustawienia → Harrys Gravatar Cache Settings), ale domyślna konfiguracja powinna działać bez problemów. Jedyną opcją, którą warto się zainteresować, jest Current Copy Option, którą w razie problemów z pobieraniem awatarów warto ustawić na WordPress Filesystem.

Trick z Gravatarem poprawił wynik w teście dla urządzeń mobilnych o kolejne dwa punkty, a w teście dla komputerów o jeden punkt.

Na drugi ogień wziąłem skrypt Google Analytics. Podobnie jak w przypadku plików z serwisu Gravatar, jedyną możliwością usunięcia tego problemu, jest trzymanie skryptu `analytics.js` na naszym serwerze. Teoretycznie nie powinniśmy tego robić, bo Google modyfikuje go bez ostrzeżenia, ale w praktyce nie dzieje się to aż tak często. Z pomocą przyszła wtyczka Cache External Scripts, która automatycznie pobiera plik `analytics.js`, zapisuje go na naszym serwerze i podmienia odpowiedni adres URL w kodzie śledzenia Google Analytics. Problem rozwiązany.

Gorzej wygląda jednak kwestia skryptu `ad_status.js`, który jest powiązany z osadzonym na naszej stronie filmem z YouTube. Nie możemy zastosować takiego samego sposobu, co w przypadku skryptu `analytics.js`, ponieważ ten skrypt jest ładowany z wewnątrz ramki `iframe`, w której znajduje się film. Wpadłem więc na pomysł, aby skorzystać z techniki lazy loading, czyli w tym przypadku z ładowania filmu dopiero po kliknięciu w niego. Na coś takiego pozwala na przykład wtyczka Lazy Load for Videos, która obsługuje filmy z serwisów YouTube i Vimeo. I rzeczywiście – problem ze skryptem `ad_status.js` zniknął, ale za to… pojawił się analogiczny problem z miniaturą filmu, pobieraną z domeny `ytimg.com`. Teoretycznie dałoby się pobierać obrazki z tej domeny na nasz serwer i ładować nasze kopie, ale wymagałoby to dość dużych modyfikacji wtyczki. Dałem sobie więc z tym spokój i zastosowałem metodę, która od początku mi się nie podobała, ale którą jednocześnie uważałem za jedyną, która się sprawdzi – czyli przeniosłem film za znacznik `<!–more–>`, dzięki czemu nie jest on widoczny na stronie głównej, a dopiero na stronie wpisu. Natomiast w normalnej sytuacji po prostu zignorowałbym ten problem.

Innym sposobem na pozbycie się problemu ładowania obrazków z zewnętrznych serwerów jest skorzystanie z lazy loadingu dla obrazków, dzięki czemu ładowane będą tylko te obrazki, które są widoczne. To jednak nie załatwi problemu tych obrazków, które są umieszczone u góry strony, przez co są cały czas widoczne, ponieważ zostaną one załadowane od razu.

Tak na marginesie: używanie wspomnianej wtyczki Lazy Load for Videos jest dobrym pomysłem, bo znacząco skraca ona czas ładowania stron z osadzonymi filmami.

Zabiegi związane ze skryptami `analytics.js` i `ad_status.js` poprawiły wynik PageSpeed Insights o osiem punktów w teście dla urządzeń mobilnych i o pięć punktów w teście dla komputerów. Warto dodać, że pozbycie się filmu YouTube z widocznego po załadowaniu strony obszaru (above the fold) rozwiązało również problem z regułą Nadaj priorytet widocznej treści.

Wszystkie wykonane do tej pory prace zaowocowały podniesieniem wyniku do 70 punktów w teście dla urządzeń mobilnych i 84 punktów w teście dla komputerów.

PageSpeed Insights

Włącz kompresję

Kolejny łatwy do usunięcia problem i kolejne zaskoczenie, jakie mnie spotkało. Podobnie jak w przypadku nagłówków `Expires`, większość firm hostingowych domyślnie kompresuje pliki po stronie serwera. Jeśli jednak nasza firma tego nie robi, wystarczy do pliku `.htaccess` dodać kilka linii:

AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf

Włączamy w ten sposób kompresję plików tekstowych za pomocą modułu `mod_deflate`. Nie ma sensu włączać kompresji dla innych typów plików, na przykład obrazków czy filmów, bo nic nam to nie da, a tylko obciąży niepotrzebnie serwer. Jeśli nasz serwer nie ma zainstalowanego modułu `mod_deflate`, możemy skorzystać z kompresji gzip:

<ifModule mod_gzip.c>
	mod_gzip_on Yes
	mod_gzip_dechunk Yes
	mod_gzip_item_include file .(html?|txt|css|js|php|pl)$
	mod_gzip_item_include handler ^cgi-script$
	mod_gzip_item_include mime ^text/.*
	mod_gzip_item_include mime ^application/x-javascript.*
	mod_gzip_item_exclude mime ^image/.*
	mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>

I teraz wspomniane na początku zaskoczenie. Firma hostingowa, z której usług korzystam (nie napiszę jaka – zainteresowani sami sobie znajdą) ma włączoną na swoich serwera kompresję gzip dla plików tekstowych, ale nie dla plików SVG, które tak naprawdę również są plikami tekstowymi (zawierają kod XML). Problem w tym, że zarówno wybrany przeze mnie motyw (Twenty Sixteen), jak i wtyczka Jetpack, korzystają z icon fonta Genericons, który ładuje spory, bo ważący 77 kB, plik `Genericons.svg`. I był to jedyny powód, dla którego reguła Włącz kompresję nie była spełniona. Niestety, samodzielne włączenie kompresji przy użyciu jednego z pokazanych wyżej sposobów, okazło się niemożliwe – konfiguracja serwera na to nie pozwalała.

Po krótkiej korespondencji ze wsparciem firmy otrzymałem zapewnienie, że temat został przekazany administratorom i pliki SVG będą kompresowane. Ja jednak nie miałem czasu na czekanie, więc postanowiłem obejść jakoś ten problem.

Napisałem krótki skrypt, który otwiera plik, pobiera jego zawartość, kompresuje ją za pomocą gzip i zwraca do przeglądarki. Kod skryptu zapisałem w pliku `/wp-content/compress.php`:

<?php
ob_start('ob_gzhandler');
$file = isset($_REQUEST['file']) ? $_REQUEST['file'] : null;
if(!empty($file)) {
	$file = $_SERVER['DOCUMENT_ROOT'].'/'.$file;
	if(pathinfo($file, PATHINFO_EXTENSION) == 'svg' && file_exists($file) && mime_content_type($file) == 'image/svg+xml') {
		$content = file_get_contents($file);
		echo $content;
	}
}
ob_flush();

Następnie do `.htaccess` dodałem regułę przekierowującą do skryptu wszystkie żądania odwołujące się do plików SVG:

RewriteCond %{REQUEST_URI} \.(svg)$
RewriteRule ^(.*) "/wp-content/compress.php?file=$1" [L]

Tym sposobem reguła Włącz kompresję została spełniona, a wynik PageSpeed Insights podskoczył do 75 punktów w teście dla urządzeń mobilnych i do 88 punktów w teście dla komputerów.

Na koniec proszę: nie róbcie tego na własnych stronach. Poczekajcie na pomoc firmy hostingowej. Ten sposób działa, ale to tylko tymczasowe obejście, a nie rozwiązanie problemu. A na pewno nie próbujcie kompresować w ten sposób plików innych niż tekstowe – to łatwy sposób na obciążenie serwera, które w skrajnych przypadkach może skończyć się blokadą strony.

Zoptymalizuj obrazy

Następny łatwy do usunięcia problem. Wystarczy skorzystać z wtyczki WP Smush, która automatycznie wykona bezstratną optymalizację obrazków znajdujących się w bibliotece mediów. Warto ją zainstalować jeszcze zanim zaczniemy ładować obrazki, ponieważ wtyczka działa „w tle” i optymalizuje obrazki podczas ich przesyłania do WordPressa. Jeśli zainstalujemy ją później, będziemy musieli wykonać masową optymalizację, która jest możliwa, ale w darmowej wersji wtyczki ograniczona do 50 obrazków na raz.

Kiedyś polecałem działającą na podobnej zasadzie wtyczkę Prizm Image, ale przez pewien czas serwery, z których korzysta, działały tak niestabilnie, że byłem zmuszony przesiąść się na alternatywne rozwiązanie.

Jeśli okaże się, że po optymalizacji PageSpeed Insights wciąż wskazuje jakieś obrazki jako niezoptymalizowane, można pobrać zoptymalizowane przez Google wersje plików i przesłać je przez SFTP na nasz serwer. Aby to zrobić wystarczy kliknąć znajdujący się pod raportem z testu link Pobierz zoptymalizowane obrazy oraz zasoby JavaScript i CSS dla tej strony.

Co ciekawe, optymalizacja obrazków nie przyniosła w moim przypadku żadnej zmiany w wyniku PageSpeed Insights. Stało się tak prawdopodobnie dlatego, że zysk z optymalizacji był niewielki (7%), a na stronie znajduje się niewiele obrazków.

Zmniejsz CSS, Zmniejsz JavaScript i Zmniejsz HTML

Kolejną czynnością, którą wypada zrobić nie tylko podczas walki o każdy punkt w PageSpeed Insights, jest kompresja (minifikacja) i złączenie w jeden plik skryptów JavaScript oraz arkuszy stylów CSS, a także kompresja samego dokumentu HTML (czyli właściwego kodu naszej strony). Wtyczek, które to umożliwiają, jest sporo, ale ja wybrałem Autoptimize, ponieważ ma ona wszystkie opcje, jakich potrzebowałem. Wtyczka spełnia swoje zadanie już przy domyślnych ustawieniach, ale warto pogrzebać chwilę w jej konfiguracji (Ustawienia → Autoptimize).

Włączyłem tylko następujące opcje:

  • Optymalizuj kod HTML
  • Optymalizuj kod JavaScript
  • Wymuś JavaScript w <head>
  • Optymalizuj kod CSS
  • Zapisz połączony skrypt/CSS jako plik statyczny

W moim przypadku wszystko poszło bezboleśnie, ale może się zdarzyć, że coś na stronie przestanie działać. Wtedy najczęściej wystarczy wykluczyć skrypt JavaScript, który po złączeniu z innymi przestał działać, w konfiguracji Autoptimize (opcja Skrypty wyłączone z Autoptimize).

Niektórzy polecają wykluczyć ze złączania bibliotekę jQuery, ale w tym konkretnym przypadku nie był to dobry pomysł (jQuery ładowała się później, niż plik ze złączonymi skryptami, tak więc wszystko przestawało działać). Może to być jednak konieczne, jeśli jakieś używamy wtyczek, które wstawiają własny kod JavaScript do kodu HTML strony.

Warto zwrócić uwagę, że ta kompresja (minifikacja) nie ma nic wspólnego z kompresją, którą włączaliśmy przy okazji reguły Włącz kompresję. Minifikacja polega na usunięciu z kodu strony zbędnych rzeczy, takich jak komentarze czy znaki końca linii.

Co ciekawe, ten krok nie przyniósł żadnej zmiany w wyniku PageSpeed Insights dla urządzeń mobilnych, ale za to w teście dla komputerów strona dostała kolejne trzy punkty.

Wyeliminuj blokujący renderowanie kod JavaScript i CSS z części strony widocznej na ekranie

To jedna z dwóch reguł, która sprawia najwięcej kłopotów. Przede wszystkim dlatego, że jej opis jest nieco enigmatyczny i na początku nie bardzo wiadomo co należy zrobić, aby pozbyć się tego problemu.

Na liście problematycznych (blokujących renderowanie strony) skryptów JavaScript i arkuszy stylów CSS znajdziemy pliki złączone przez Autoptimize oraz (co gorsze) fonty z Google Fonts, których używa motyw Twenty Sixteen. Niestety, aby to wszystko naprawić będziemy musieli pogrzebać trochę w kodzie. Zakładam, że korzystamy z motywu potomnego i nie dotykamy w ogóle plików motywu głównego. Wszystkie modyfikacje wrzucamy do pliku `functions.php` znajdującego się w katalogu motywu potomnego.

Zaczniemy od pliku ze złączonymi skryptami JavaScript. Aby przestał on blokować renderowanie strony wystarczy załadować go asynchronicznie, czyli w taki sposób, aby przeglądarka nie czekała z wyświetleniem strony na jego załadowanie. Możemy to zrobić dodając do znacznika `<script>` atrybut `async`. Oczywiście nie będziemy robili tego ręcznie w kodzie HTML, bo tak się w WordPressie po prostu nie da. Na szczęście Autoptimize oferuje filtr, za pomocą którego możemy dodać ten atrybut do znacznika ładującego plik ze złączonymi skryptami JavaScript. Robimy to w ten sposób (trzeba pamiętać o spacji po ciągu „async”):

function wpzen_defer() {
	return 'async ';
}
add_filter('autoptimize_filter_js_defer', 'wpzen_defer');

Niestety, takie asynchroniczne ładowanie skryptów JavaScript ma też swoje wady. Najczęściej problemy występują na stronach, gdzie skrypty JavaScript są niezbędne do ich działania. Często możemy też zaobserwować niezbyt dobrze wyglądające opóźnienie w inicjalizacji skryptów, które wynika z tego, że strona (kod HTML) jest już wyświetlona, a skrypty JS jeszcze się nie załadowały, więc nie zrobiły swojej roboty. Wszystko tu zależy od konkretnego przypadku, ale dobrze stworzona strona nie powinna się całkowicie od tego rozsypać.

Teraz trzeba zrobić coś z fontami Google Fonts. Ponieważ są one ładowane jako arkusze stylów CSS, nie możemy ich załadować asynchronicznie (tak jak to zrobiliśmy ze skryptami JavaScript). W ustawieniach Autoptimize możemy globalnie (dla całej strony) wyłączyć ładowanie Google Fonts – wystarczy zaznaczyć opcję Usunąć Google Fonts. Tyle że w tym momencie nasza piękna typografia przestaje być taka piękna i wszystkie teksty są wyświetlane przy użyciu domyślnych fontów. Na szczęście istnieje biblioteka Web Font Loader, która potrafi między innymi ładować fonty w sposób nie blokujący renderowania strony.

Najpierw musimy sprawdzić jakich fontów używa nasz motyw. Najprościej jest zajrzeć do narzędzi deweloperskich w przeglądarce i skopiować adres URL ładowanego z domeny `fonts.googleapis.com` arkusza stylów. W przypadku motywu Twenty Sixteen URL ten wygląda tak:

https://fonts.googleapis.com/css?family=Merriweather%3A400%2C700%2C900%2C400italic%2C700italic%2C900italic%7CMontserrat%3A400%2C700%7CInconsolata%3A400&subset=latin%2Clatin-ext

a po „zdekodowaniu” tak:

https://fonts.googleapis.com/css?family=Merriweather:400,700,900,400italic,700italic,900italic|Montserrat:400,700|Inconsolata:400&subset=latin,latin-ext

Teraz łatwo możemy wyciągnąć z niego nazwy i warianty fontów, które musimy samodzielnie załadować przy użyciu Web Font Loadera.

Aby skorzystać z biblioteki wystarczy do pliku `functions.php` wstawić taki kod:

function wpzen_load_google_fonts_script() {
	wp_enqueue_script('webfont-loader', '//ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js');
}
add_action('wp_enqueue_scripts', 'wpzen_load_google_fonts_script');

function wpzen_load_google_fonts_footer() {
?>
	<script type="text/javascript">
		WebFont.load({
			google: {
				families: ['Merriweather:400,700,900,400italic,700italic,900italic:latin,latin-ext',
						   'Montserrat:400,700:latin,latin-ext',
						   'Inconsolata:400:latin,latin-ext']
			}
		});
	</script>
<?php
}
add_action('wp_footer', 'wpzen_load_google_fonts_footer');

Funkcja `wpzen_load_google_fonts_script()` ładuje bibliotekę, a funkcja `wpzen_load_google_fonts_footer()` ładuje trzy wybrane przez nas fonty. Koniecznie trzeba zwrócić uwagę na format parametrów dla każdego z fontów – brak dwukropka czy przecinka spowoduje, że nic nie będzie działać. Oczywiście możemy tam sobie dodać dowolne inne fonty – biblioteka obsługuje również fonty z serwisów Typekit, FontdeckFonts.com, a także własne fonty.

Na koniec powinniśmy wymusić asynchroniczne ładowanie biblioteki Web Font Loader – można to zrobić za pomocą takiej prostej funkcji:

function wpzen_async_scripts($tag, $handle, $src) {
	$async_scripts = array('webfont-loader');
	
	if(in_array($handle, $async_scripts)) {
		return '<script type="text/javascript" src="'.$src.'" async="async"></script>'."\n";
	}
	
	return $tag;
}
add_filter('script_loader_tag', 'wpzen_async_scripts', 10, 3);

Funkcja ta może nam się jeszcze kiedyś przydać, na przykład gdy dodamy do strony kolejne zewnętrzne skrypty – wtedy wystarczy do tablicy `$acyns_scripts` dodać kolejną nazwę.

Wadą korzystania z tego sposobu ładowania zewnętrznych fontów jest możliwość występowania zjawiska zwanego Flash of Unstyled Text (FOUT), czyli pojawienia się na krótką chwilę tekstu wyświetlanego domyślnym fontem. Efekt ten jest spowodowany tym, że strona może być wyrenderowana przez przeglądarkę jeszcze zanim fonty zostaną załadowane. Nie jest to jednak wielki problem, szczególnie że występuje tylko przy pierwszym otwarciu naszej strony przez użytkownika – przy kolejnych odsłonach pliki są pobierane z cache jego przeglądarki. Warto jednak dodać, że to zjawisko może występować również przy ładowaniu zewnętrznych fontów w „tradycyjny” sposób.

Został nam więc już tylko arkusz stylów CSS blokujący renderowanie strony. Podobnie jak w przypadku fontów, nie mamy możliwości załadowania go w sposób asynchroniczny. Teoretycznie da się to zrobić za pomocą JavaScript (np. korzystając z loadCSS), ale nie jest to zalecane dla krytycznych arkuszy stylów (a nasz taki właśnie jest – to w końcu złączone wszystkie pliki CSS). Moim pierwszym pomysłem było wykorzystanie wtyczki Autoptimize i jej opcji Także łączyć razem CSS z treści strony?, która wstawia całą zawartość plików CSS bezpośrednio do kodu HTML. Efekt na pierwszy rzut oka był pozytywny: problem zniknął z raportu PageSpeed Insights. Niestety, w jego miejsce pojawił się inny – Nadaj priorytet widocznej treści. No i oczywiście rozmiar dokumentu HTML powiększył się o mniej więcej 40 kB.

Warto jednak zauważyć, że wyniki testów poszybowały w górę (100 punktów w teście dla urządzeń mobilnych i 97 w teście dla komputerów).

PageSpeed Insights

W normalnych warunkach uznałbym te wyniki za świetne i nie drążył dalej tematu. Jak już wspomniałem na wstępie, wynik powyżej 85 punktów jest uznawany za dobry. Ale moim celem nie było osiągnięcie dobrego wyniku, ale 100 punktów w obu testach.

Poza tym bardzo nie podobało mi się włączenie całego arkusza stylów CSS do kodu HTML.

Nadaj priorytet widocznej treści

Ta reguła mówi nam, że powinniśmy umożliwić przeglądarce jak najszybsze wyświetenie tej części strony, która jest zaraz po załadowaniu widoczna w oknie przeglądarki (tzw. above the fold). U mnie ten problem pojawił się gdy wrzuciłem cały arkusz stylów do kodu HTML strony, a to dlatego, że kodu CSS było tam po prostu o wiele za dużo.

Priorytetyzacja widocznej treści to dość szerokie zagadnienie, związane zarówno ze strukturą kodu HTML, jak i stylów CSS. Ale na szczęście istnieje coś, co pozwala w stosunkowo łatwy sposób osiągnąć cel – a jest to Critical Path CSS. W skrócie chodzi o umieszczenie na początku nagłówka strony (w sekcji `<head>`) tych stylów CSS, które są potrzebne do wyświetlenia widocznego fragmentu strony (są krytyczne dla naszego serwisu). Oczywiście ręczne wyodrębnianie takich stylów byłoby dość czasochłonne, dlatego powstały do tego specjalne narzędzia. Najprostsze w obsłudze są narzędzia online: Critical Path CSS Generator i jego płatna, prostsza w obsłudze wersja – Critical CSS.

Critical Path CSS Generator wymaga od nas podania adresu naszej strony i wklejenia całej zawartości arkusza stylów CSS. Po kliknięciu przycisku Create Critical Path CSS wygenerowany zostanie kod CSS, który trzeba umieścić na naszej stronie. Można to zrobić korzystając (znowu) z wtyczki Autoptimize – w jej ustawieniach znajdziemy opcję Włączyć CSS w treść strony i opóźnić jego ładowanie?, której zaznaczenie spowoduje pojawienie się pola do wprowadzenia wygenerowanych stylów CSS. Jednocześnie główny arkusz stylów (połączenie wszystkich plików CSS) zostanie załadowany asynchronicznie za pomocą skryptu JavaScript.

Efekt? 100/100 w obu testach!

PageSpeed Insights - 100/100

Narzędzie Critical CSS jest o tyle prostsze, że wystarczy podać mu adres naszej strony – samo pobiera sobie arkusze stylów CSS.

Trzeba pamiętać, że taki krytyczny arkusz stylów CSS może wyglądać różnie w zależności od struktury danej podstrony – prawie na pewno ten ze strony głównej nie będzie „pasował” do podstrony z treścią wpisu. Dlatego uważam, że ta zabawa to w większości przypadków tylko „sztuka dla sztuki” – korzyści są zdecydowanie zbyt małe w stosunku do nakładu pracy (szczególnie w przypadku bardziej rozbudowanych stron).

Bonus: Wygoda użytkowników

W raporcie z testu dla urządzeń mobilnych znajduje się sekcja zatytułowana Wygoda użytkowników, w której znajdziemy zalecenia dotyczące usprawnień strony pod kątem komfortu korzystania z niej na małych ekranach urządzeń mobilnych.

PageSpeed Insights - wygoda użytkownika

Najczęściej pojawiającymi się problemami są Dobierz odpowiedni rozmiar elementów dotykowychUżywaj czytelnych rozmiarów czcionek. Pierwsza reguła wymaga od nas powiększenia rozmiaru elementów dotykowych (np. linków) i zwiększenia odstępu pomiędzy nimi (wysokość linii i marginesy). Druga reguła mówi z kolei, że gdzieś zastosowaliśmy zbyt mały rozmiar tekstu. Nie ma w tym nic skomplikowanego i bardzo łatwo jest wprowadzić odpowiednie poprawki.

Oczywiście reguły z tej sekcji nie mają nic wspólnego z prędkością naszej strony.

Podsumowanie

Wynik PageSpeed Insights zależy od bardzo wielu czynników. Każda strona może wymagać innych zabiegów optymalizacyjnych, jednak część z opisanych przeze mnie działań sprawdzi się w każdym przypadku. Moim celem było pokazanie, jak można spełnić poszczególne reguły PageSpeed Insights, bo ich opisy często są niewystarczające, szczególnie dla mniej zaawansowanych użytkowników.

Jak już wcześniej napisałem, dążenie za wszelką cenę do osiągnięcia maksymalnego wyniku w teście Google PageSpeed Insights nie ma większego sensu. Niektóre z wykonanych przeze mnie zabiegów mogą spowodować problemy ze skryptami JavaScript, a inne (jak na przykład generowanie Critical Path CSS) są dość skomplikowane. Nie należy traktować wyniku PageSpeed Insights jako jedynego słusznego wyznacznika szybkości strony. To oczywiście bardzo ważny wskaźnik, ale nie zapominajmy, że poświęcony na optymalizacje czas musi się nam w jakiś sposób zwrócić i dać jakieś wymierne korzyści. Jeśli osiągnęliśmy wynik na poziomie co najmniej 85 punktów, to możemy sobie pogratulować i zająć się czymś pożyteczniejszym.

Pamiętajmy też, że PageSpeed Insights nie jest jedynym testem sprawdzającym wydajność stron internetowych – warto wspomnieć jeszcze o YSlow, Pingdom Website Speed Test, WebPageTest GTmetrix (który korzysta m. in. z YSlow). Każde z tych narzędzi ma własny zestaw reguł weryfikujących szybkość strony, dlatego też osiągnięcie maksymalnego wyniku w jednym z nich wcale nie gwarantuje tego samego w innym.

Reguły, za pomocą których wszystkie te narzędzia weryfikują wydajność naszej strony, mają nam przede wszystkim pomóc w jak najlepszym zoptymalizowaniu naszej witryny. Sami możemy zdecydować, że dana reguła nas nie interesuje – tak jak na przykład sugerowałem przy okazji problemów z osadzonymi filmami z YouTube. Zachęcam do samodzielnych eksperymentów i do korzystania z moich porad w innej kolejności – może się okazać, że pominięcie któregoś z etapów nie odbije się w znaczący sposób na wyniku testu. Warto też sprawdzać (na przykład za pomocą jednego z alternatywnych narzędzi) czas ładowania strony i jej rozmiar – są to parametry, których PageSpeed Insights nie pokazuje wprost, a które są istotne z punktu widzenia wygody użytkowników.

Bezpośredni link