Zoptymalizuj wczytywanie i renderowanie czcionek WebFont

Ilia Grigorik

„Pełna” czcionka WebFonts zawierająca wszystkie stylistyczne warianty, których być może nie potrzebujesz, oraz wszystkie glify, które mogą stać się nieużywane, może ułatwić pobieranie plików o rozmiarze wielu megabajtów. Z tego posta dowiesz się, jak zoptymalizować ładowanie czcionek WebFonts, aby użytkownicy pobierali tylko te, z których korzystają.

Aby rozwiązać problem dużych plików zawierających wszystkie warianty, reguła CSS @font-face została zaprojektowana w taki sposób, aby umożliwić podział rodziny czcionek na zbiór zasobów. Dotyczy to na przykład podzbiorów Unicode i różnych wariantów stylów.

Po tych deklaracjach przeglądarka określa wymagane podzbiory i warianty i pobiera minimalny zestaw niezbędny do wyrenderowania tekstu, co jest bardzo wygodne. Jeśli jednak nie zachowasz ostrożności, może to też doprowadzić do wąskiego gardła wydajności na krytycznej ścieżce renderowania i opóźnić renderowanie tekstu.

Działanie domyślne

Leniwe ładowanie czcionek niesie ze sobą istotne, ukryte konsekwencje, które mogą opóźniać renderowanie tekstu. Przeglądarka musi utworzyć drzewo renderowania, które jest zależne od drzew DOM i CSSOM, zanim będzie wiedzieć, które zasoby czcionek potrzebuje do renderowania tekstu. W związku z tym żądania czcionek są opóźnione ze znacznym opóźnieniem w stosunku do innych zasobów krytycznych, a możliwość renderowania tekstu przez przeglądarkę może zostać zablokowana do czasu pobrania zasobu.

Krytyczna ścieżka renderowania czcionki

  1. Przeglądarka wysyła żądanie dokumentu HTML.
  2. Przeglądarka rozpoczyna analizę odpowiedzi HTML i tworzenie DOM.
  3. Przeglądarka wykrywa zasoby CSS, JS i inne oraz wysyła żądania.
  4. Przeglądarka generuje CSSOM po otrzymaniu całej zawartości CSS i łączy ją z drzewem DOM, aby utworzyć drzewo renderowania.
    • Żądania czcionek są wysyłane po tym, jak drzewo renderowania wskaże, które warianty czcionek są potrzebne do wyrenderowania wskazanego tekstu na stronie.
  5. Przeglądarka wyświetla układ i maluje zawartość na ekranie.
    • Jeśli czcionka nie jest jeszcze dostępna, przeglądarka może nie wyrenderować żadnych pikseli tekstowych.
    • Gdy czcionka jest dostępna, przeglądarka maluje piksele tekstu.

Wyścig między pierwszym wyrenderowaniem treści strony, który ma miejsce zaraz po utworzeniu drzewa renderowania, a żądanie zasobu czcionki powoduje powstanie „problemu z pustym tekstem”, w którym przeglądarka może wyrenderować układ strony z pominięciem tekstu.

Dzięki wstępnemu wczytywaniu WebFonts i używaniu font-display do kontrolowania zachowania przeglądarek w przypadku niedostępnych czcionek możesz zapobiec wyświetlaniu pustych stron i przesunięć układu spowodowanego wczytywaniem czcionek.

Wstępnie wczytuj zasoby WebFont

Jeśli istnieje duże prawdopodobieństwo, że Twoja strona będzie potrzebować określonej czcionki WebFont hostowanej pod adresem URL, który znasz z wyprzedzeniem, możesz skorzystać z priorytetu zasobów. Użycie elementu <link rel="preload"> spowoduje wywołanie żądania czcionki WebFont na wcześniejszym etapie krytycznej ścieżki renderowania, bez konieczności oczekiwania na utworzenie CSSOM.

Dostosowywanie opóźnienia renderowania tekstu

Wstępne wczytywanie zwiększa prawdopodobieństwo, że czcionka WebFont będzie dostępna podczas renderowania treści strony, ale nie daje żadnych gwarancji. Nadal musisz wziąć pod uwagę zachowanie przeglądarek podczas renderowania tekstu korzystającego z metody font-family, który nie jest jeszcze dostępny.

W poście Unikaj niewidocznego tekstu podczas wczytywania czcionki widać, że domyślne działanie przeglądarki nie jest spójne. Możesz jednak skonfigurować nowoczesne przeglądarki, korzystając z metody font-display.

Obsługa przeglądarek

  • 60
  • 79
  • 58
  • 11.1

Źródło

Podobnie jak w przypadku niektórych przeglądarek, funkcja font-display dzieli czas trwania pobierania czcionki na 3 główne okresy:

  1. Pierwsza to okres bloku czcionek. Jeśli krój czcionki nie zostanie wczytany w tym okresie, każdy element, który próbuje z niej skorzystać, będzie renderowany z niewidoczną zastępczą kropką czcionki. Jeśli krój czcionki uda się wczytać w okresie blokowania, będzie używany normalnie.
  2. Okres zamiany czcionek ma miejsce bezpośrednio po okresie bloku czcionki. Jeśli w tym czasie krój czcionki nie zostanie wczytany, każdy element, który próbuje z niej skorzystać, będzie renderowany z zastępczą kropką czcionki. Jeśli krój czcionki uda się wczytać w czasie zamiany, będzie ona używana normalnie.
  3. Okres awarii czcionek następuje natychmiast po okresie zamiany czcionki. Jeśli w momencie rozpoczęcia tego okresu krój czcionki nie zostanie jeszcze wczytany, zostanie oznaczony jako nieudany wczytywanie, co spowoduje normalne działanie zastępczej czcionki. W przeciwnym razie krój czcionki będzie używany normalnie.

Jeśli zrozumiesz te przedziały, za pomocą font-display możesz określić, jak powinna wyglądać czcionka w zależności od tego, czy została pobrana.

Aby korzystać z właściwości font-display, dodaj ją do reguł @font-face:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  font-display: auto; /* or block, swap, fallback, optional */
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
       url('/fonts/awesome-l.woff') format('woff'),
       url('/fonts/awesome-l.ttf') format('truetype'),
       url('/fonts/awesome-l.eot') format('embedded-opentype');
  unicode-range: U+000-5FF; /* Latin glyphs */
}

font-display obsługuje obecnie ten zakres wartości:

  • auto
  • block
  • swap
  • fallback
  • optional

Więcej informacji o wstępnym wczytywaniu czcionek i właściwości font-display znajdziesz w tych postach:

Font Wczytuję API

Wspólne stosowanie <link rel="preload"> i CSS font-display zapewniają dużą kontrolę nad wczytywaniem i renderowaniem czcionek bez konieczności znacznego zwiększania nakładu pracy. Jeśli jednak potrzebujesz dodatkowych dostosowań i chcesz ponosić koszty związane z uruchamianiem kodu JavaScript, możesz skorzystać z innej opcji.

Font Ładuję API udostępnia interfejs do obsługi skryptów, który umożliwia definiowanie i manipulowanie tarczami czcionek CSS, śledzenie postępu pobierania i zastępowanie domyślnego działania leniwego ładowania. Jeśli na przykład masz pewność, że wymagana jest konkretna wersja czcionki, możesz ją zdefiniować i poinformować przeglądarkę, by zainicjowała natychmiastowe pobieranie zasobu czcionki:

Obsługa przeglądarek

  • 35
  • 79
  • 41
  • 10

Źródło

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
  style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});

// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
  // apply the font (which may re-render text and cause a page reflow)
  // after the font has finished downloading
  document.fonts.add(font);
  document.body.style.fontFamily = "Awesome Font, serif";

  // OR... by default the content is hidden,
  // and it's rendered after the font is available
  var content = document.getElementById("content");
  content.style.visibility = "visible";

  // OR... apply your own render strategy here...
});

Ponieważ możesz sprawdzać stan czcionki (za pomocą metody check()) i śledzić postęp pobierania, możesz też zdefiniować niestandardową strategię renderowania tekstu na swoich stronach:

  • Możesz wstrzymać renderowanie tekstu, dopóki czcionka nie będzie dostępna.
  • Możesz ustawić niestandardowy limit czasu dla każdej czcionki.
  • Możesz użyć czcionki zastępczej, aby odblokować renderowanie i wstrzyknąć nowy styl, który będzie korzystał z wybranej czcionki, gdy czcionka będzie dostępna.

A co najlepsze, powyższe strategie możesz łączyć i dopasowywać do różnych treści na stronie. Możesz na przykład opóźnić renderowanie tekstu w niektórych sekcjach do momentu udostępnienia czcionki, użyć czcionki zastępczej, a następnie ponownie renderować czcionkę po zakończeniu jej pobierania.

Właściwe buforowanie jest konieczne

Zasoby czcionek to zwykle zasoby statyczne, które nie są często aktualizowane. W związku z tym idealnie nadają się do długiego okresu ważności maksymalnego okresu ważności – upewnij się, że określono zarówno warunkowy nagłówek ETag, jak i optymalną zasadę kontroli pamięci podręcznej dla wszystkich zasobów czcionek.

Jeśli Twoja aplikacja internetowa korzysta z mechanizmu Service worker, udostępnianie zasobów czcionek za pomocą strategii priorytetowej w pamięci podręcznej jest odpowiednie w większości przypadków.

Nie przechowuj czcionek za pomocą localStorage lub IndexedDB. Każda z nich ma własny zestaw problemów z wydajnością. Pamięć podręczna HTTP przeglądarki zapewnia najlepszy i najsilniejszy mechanizm dostarczania zasobów czcionek do przeglądarki.

Lista kontrolna ładowania czcionek WebFont

  • Dostosuj wczytywanie i renderowanie czcionek za pomocą <link rel="preload">, font-display lub interfejsu Font Loading API: domyślne działanie leniwego ładowania może opóźniać renderowanie tekstu. Te funkcje platformy internetowej umożliwiają zastąpienie tego zachowania w przypadku konkretnych czcionek oraz określenie niestandardowych strategii renderowania i limitu czasu dla różnych treści na stronie.
  • Ustal zasady ponownej walidacji i optymalnego buforowania: czcionki to zasoby statyczne, które nie są często aktualizowane. Sprawdź, czy Twoje serwery udostępniają długoterminową sygnaturę czasową i token ponownej walidacji, co umożliwi skuteczne wykorzystywanie czcionek na różnych stronach. Jeśli korzystasz z skrypcji service worker, najważniejsza jest strategia oparta na pamięci podręcznej.

Automatyczne testowanie sposobu ładowania czcionek WebFont za pomocą Lighthouse

Narzędzie Lighthouse może pomóc w automatyzacji procesu, aby upewnić się, że postępujesz zgodnie ze sprawdzonymi metodami optymalizacji czcionek internetowych.

Te audyty pomogą Ci dopilnować, aby Twoje strony nadal były zgodne ze sprawdzonymi metodami optymalizacji czcionek internetowych: