Notes · Notatka 001 · Wydajność webu
Gdzie statyczna strona ukrywała ostatnie 18 punktów
Obrazy były skompresowane, JavaScript mieścił się w trzech plikach, a frameworka nie było. Lighthouse nadal pokazywał 82. Brakujące punkty kryły się w trzech miejscach, które narzędzie nazwało, lecz nie wyjaśniło.
Założyciel, BLN Global · · 7 min czytania
Krótka odpowiedź
Obrazy i JavaScript były już w porządku. Punkty traciliśmy w trzech miejscach. Po pierwsze, kontrola pomijająca zbędną pracę sama odczytywała układ i zmuszała przeglądarkę do obliczeń. Po drugie, arkusz stylów i zewnętrzne fonty opóźniały pierwsze renderowanie o 600 ms. Osadziliśmy CSS na stronie, a fonty przenieśliśmy na własny serwer. Po trzecie, 6 z 24 ostrzeżeń o kontraście było fałszywych. Pełne skanowanie wykryło potem 13 stron pominiętych w próbce.
Ta strona nie używa frameworka. Skrypty Python generują zwykły HTML, style mieszczą się w jednym pliku CSS, a JavaScript w trzech małych plikach. Obrazy powstają w WebP, w trzech rozmiarach. Wszystkie oczywiste poprawki wydajności były już gotowe.
Wynik mobilny utknął na 82.
Po usunięciu oczywistych błędów brakujące punkty nie kryły się w jednej dużej usterce. Rozłożyły się na trzy miejsca. Żeby znaleźć je wszystkie, trzeba było zrozumieć sens ostrzeżenia, a nie tylko je przeczytać. co ma na myśli wymagało zrozumienia.
Pierwsze miejsce: sama kontrola napisana po to, by pominąć pracę
Ostrzeżenie Lighthouse „wymuszone przeliczanie układu” (forced reflow) oznacza, że JavaScript każe przeglądarce zbyt wcześnie obliczyć układ strony. Przeglądarka zbiera zmiany stylów i stosuje je naraz. Gdy kod wcześniej odczyta wymiary, musi od razu przeliczyć zaległe zmiany.
Ostrzeżenie wskazywało linię w kodzie, ale w tej linii nie było widać żadnego pomiaru. Znaleźliśmy go po trzech podejściach.
- W pierwszej rundzie
getComputedStyleUsunęliśmy wywołania. Wynik bez zmian. - W drugiej rundzie wyszedł prawdziwy winowajca: napisaliśmy kod, który miał pomijać zbędną pracę
if (window.scrollY > 0)sprawdzenie. Ono samo odczytywało układ. Wiersz, który miał pominąć tę pracę, właśnie ją uruchamiał. - W trzeciej rundzie usunęliśmy funkcję. Stan początkowy definiował już CSS, więc JavaScript nie musiał tworzyć go ponownie.
Został jeszcze jeden schemat void element.offsetWidth było. To popularny i uznany trik, który celowo wymusza układ, by ponownie uruchomić przejście. Zastąpiły go dwa kolejne requestAnimationFrame wstawiliśmy go. Robi to samo i nie rozpycha układu.
function uruchomPonownie(fn) { /* Gdy karta jest w tle, rAF nie ruszy i demo zostanie puste. */ if (document.hidden) { fn(); return; } requestAnimationFrame(function () { requestAnimationFrame(fn); }); }
Ten przypadek nauczył nas jednego: ostrzeżenie o wydajności często nie mówi „robisz za dużo”, lecz „robisz to w złym momencie”.
Drugie miejsce: 600 ms przed pierwszym renderowaniem
Drugie ostrzeżenie dotyczyło zasobów blokujących pierwsze wyświetlenie. Po otwarciu strony przeglądarka pobierała i przetwarzała najpierw arkusz stylów, potem fonty. Dopiero wtedy zaczynała rysować. Zmierzone opóźnienie wyniosło 600 milisekund.
Wpięliśmy plik stylów w stronę
Osobny plik CSS przy drugiej wizycie przychodzi z cache’u. To plus. Przy pierwszej dokłada jednak dodatkową rundę tam i z powrotem, a pierwsza wizyta to dokładnie to, co widzi ktoś z wyniku wyszukiwania. Podczas publikacji zmniejszamy CSS i osadzamy go w stronie. Zmierzyliśmy: po kompresji Brotli wersja osadzona była mniejsza niż osobny plik razem z drugim żądaniem.
Przenieśliśmy fonty na własny serwer
Setup z Google Fonts szedł do dwóch źródeł: po styl fonts.googleapis.com, dla plików fonts.gstatic.com. Każdy nowy host wymaga rozwiązania DNS, uzgodnienia TLS i kolejnego połączenia. Gdy go usunęliśmy, pomiar pokazał:
Tyle danych fontów pobiera strona po turecku. Zamiast 6 plików z 2 zewnętrznych źródeł ma 3 pliki z jednego źródła.
unicode-range Na podstawie pól wydzieliliśmy podzbiory, które strona po turecku naprawdę pobierze (latin + latin-ext), i zmierzyliśmy rozmiar każdego pliku. Druga strona z tego repozytorium assets/fonts rzeczywisty rozmiar plików.Osobno opisaliśmy, jak kurczyły się fonty i gdzie płacisz cenę, gdy otwierasz projekt na dziesięć języków: dziesięć języków, trzy pliki fontów.
Trzecie miejsce: tu narzędzie się myli
Test dostępności zgłosił 24 ostrzeżenia o kontraście kolorów. Gdybyśmy poprawili je bez sprawdzania, zepsulibyśmy połowę projektu. 6 ostrzeżeń było błędnych.
Powód content-visibility:auto było. Ta funkcja odkłada renderowanie fragmentów poza ekranem i przyspiesza pierwsze wyświetlenie. Dokładnie o to nam chodziło. Obliczony kolor odłożonego fragmentu nie trafiał jednak do narzędzia audytowego, więc zgłaszało „białe na białym”. Na ekranie tego problemu nie było.
Sprawdziliśmy każdą proporcję w przeglądarce. 18 ostrzeżeń było trafnych, więc je poprawiliśmy. 6 wynikało ze ślepej plamki narzędzia. content-visibility usunęliśmy go tylko z dwóch wadliwych sekcji. W pozostałych został.
Ostrzeżenie z audytu nie dowodzi, że masz błąd do naprawy. Traktuj je jak tezę. Najpierw ją sprawdź, potem popraw kod. Na tej stronie ta lekcja wróciła jeszcze dwa razy. Jeden z tych przypadków to w notatce o korekcie językowej opisujemy.
I rana, którą sami sobie zadaliśmy
Aby uniknąć przesunięć układu, wszystkim obrazom width i height Dodaliśmy atrybut. Dobry ruch. Przeglądarka rezerwuje miejsce na obraz bez pobierania go. Ale boksy demo się rozsypały: część grafik narysowała się na 58 pikseli szerokości i 1500 pikseli wysokości.
Powód: w HTML width i height atrybuty podpowiadają układ, a w CSS height uzupełniają jego wartość. W projekcie dla tych pól tylko aspect-ratio kod określał, height było puste. atrybut trafił właśnie tam i nadpisał proporcje. Poprawka w jednej linijce:
img{max-width:100%;height:auto;display:block}
I tu skanowanie naprawdę pomaga
Gdy strona główna miała 100, temat wyglądał na zamknięty. Nie był. Zmierzyliśmy próbkę. Witryny wszystkie 150 stron Przepuściliśmy je po kolei przez Lighthouse. Wynik: 137 stron miało 100 w czterech kategoriach, nie 13 stron. Dostępność, dobre praktyki i SEO miały 100 na każdej stronie. Odstawała tylko wydajność.
11 z 13 stron było w tym samym języku: po arabsku. Najniższy wynik: 83.
/ar/safecoast/ 83 /ar/laya/ 84 /ar/localmind/ 84 /ar/adforge/ 85 /ar/garanti/ 85 /ar/gtin/ 86 /ar/visionguard/ 86 /ar/ 89 /ar/growthos/ 97 /ar/dream/ 99 /ar/twin/ 99
Lighthouse wskazał powód wprost: Font wczytany → ar.woff2. Arabski font ładował się za późno i układał stronę od nowa. Metryki arabskiego fontu zapasowego mocno różniły się od Noto Sans Arabic, więc skok był duży. Poprawka wynikała z decyzji, którą podjęliśmy już przy Martian Mono: zamień nie optional.
Przesunięcia układu na stronach arabskich (CLS)
Sedno nie dotyczy wydajności. Gdy bierzesz próbkę i mówisz „strona ma 100”, składasz obietnicę na temat strony, której nie zmierzyłeś. Piętnaście stron stało tak miesiącami z wynikiem 83, bo nikt do nich nie zajrzał.
Granica wyniku
Sam wynik pochodzi z laboratorium. Zakłada stałe urządzenie i model sieci. Telefon oraz zasięg prawdziwego użytkownika mogą działać gorzej. W kolejnych pomiarach tej samej strony wynik waha się od 98 do 100. Wynik 100 nie oznacza „szybko dla każdego”, lecz „usunęliśmy wszystkie mierzalne przeszkody”. Gdy zbierzemy dane prawdziwych użytkowników, sprawdzimy dane terenowe Chrome.
Wspólny mianownik tych trzech poprawek: żadna nie polegała na dokładaniu pracy. Usunęliśmy pracę wykonywaną w złym momencie albo taką, której nie trzeba było robić.