Zoptymalizuj wczytywanie i renderowanie czcionek WebFont

„Pełna” czcionka WebFonts obejmująca wszystkie style stylistyczne, których nie potrzebujesz, oraz wszystkie glify, które mogą być nieużywane, może z łatwością doprowadzić do pobrania treści o wielkości wielu megabajtów. Z tego posta dowiesz się, jak zoptymalizować wczytywanie czcionek WebFonts, aby użytkownicy pobierali tylko to, z czego będą korzystać.

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

Biorąc pod uwagę te deklaracje, przeglądarka określa wymagane podzbiory i warianty i pobiera minimalny zestaw niezbędny do renderowania tekstu, co jest bardzo wygodne. Jeśli jednak nie zachowasz ostrożności, może to też spowodować wąskie gardło 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 rozpozna zasoby czcionki potrzebne do wyrenderowania tekstu. W rezultacie żądania czcionek są opóźnione znacznie po osiągnięciu innych zasobów krytycznych, a renderowanie tekstu przez przeglądarkę może zostać zablokowane do czasu pobrania zasobu.

Krytyczna ścieżka renderowania czcionki

  1. Przeglądarka wysyła żądanie udostępnienia dokumentu HTML.
  2. Przeglądarka rozpoczyna analizowanie odpowiedzi HTML i tworzenie DOM.
  3. Przeglądarka wykrywa kod CSS, JS i inne zasoby 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, gdy drzewo renderowania wskaże, które warianty czcionek są potrzebne do wyrenderowania określonego tekstu na stronie.
  5. Przeglądarka wyświetla układ i maluje treść 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 tekstowe.

„Wyścig” między pierwszym wyrenderowaniem zawartości strony, który następuje krótko po zbudowaniu drzewa renderowania, a żądanie zasobu czcionki to źródło „problemu z pustym tekstem”, w którym przeglądarka może renderować układ strony, ale pomija tekst.

Dzięki wstępnemu wczytywaniu WebFonts i używaniu font-display do kontrolowania zachowania przeglądarek w przypadku niedostępnych czcionek możesz zapobiec pustym stronom i przesunięciu układu z powodu ładowania czcionek.

Wstępnie wczytuj zasoby WebFont

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

Dostosowywanie opóźnienia renderowania tekstu

Wstępne wczytywanie zwiększa prawdopodobieństwo pojawienia się czcionki WebFont, gdy zostanie wyrenderowana zawartość strony, ale nie daje takiej 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 ładowania czcionki widać, że domyślne działanie przeglądarki nie jest spójne. Możesz jednak określić działanie współczesnych przeglądarek, 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 pobrania czcionki na 3 główne przedziały czasu:

  1. Pierwszy okres to okres bloku czcionek. Jeśli w tym czasie nie zostanie wczytana krój czcionki, każdy element, który próbuje z niej skorzystać, będzie musiał renderować się za pomocą niewidocznej zastępczej kroju czcionki. Jeśli krój czcionki zostanie wczytany w okresie blokowania, będzie używany normalnie.
  2. Okres zamiany czcionki ma miejsce bezpośrednio po okresie blokowania czcionki. Jeśli w tym okresie nie zostanie wczytana krój czcionki, każdy element, który próbuje z niej skorzystać, będzie musiał renderować się zastępczą krojem czcionki. Jeśli krój czcionki zostanie wczytany w okresie zamiany, będzie on używany normalnie.
  3. Okres błędu czcionki rozpoczyna się bezpośrednio po okresie zamiany czcionki. Jeśli krój czcionki nie został jeszcze wczytany przed rozpoczęciem tego okresu, zostanie wyświetlony jako nieudane wczytywanie, co spowoduje normalną kreację zastępczą. W przeciwnym razie krój czcionki będzie używany normalnie.

Poznanie tych okresów oznacza, że możesz za pomocą font-display określić sposób renderowania czcionki w zależności od tego, czy została ona 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:

Interfejs Font Wczytuję API

Połączenie <link rel="preload"> i CSS font-display zapewnia dużą kontrolę nad wczytywaniem i renderowaniem czcionek, które nie wymagają znacznego nakładu pracy. Jeśli jednak potrzebujesz dodatkowych dostosowań i chcesz narażać się na koszt związany z uruchamianiem JavaScriptu, możesz skorzystać z innej opcji.

Interfejs Font Wczytuję API ma interfejs do obsługi skryptów, który pozwala definiować i manipulować krojami czcionek CSS, śledzić postęp pobierania oraz zastępować domyślne zachowanie leniwego ładowania. Jeśli na przykład masz pewność, że określony wariant czcionki jest wymagany, możesz zdefiniować go i poinformować przeglądarkę, aby 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 jej pobierania, możesz też zdefiniować niestandardową strategię renderowania tekstu na stronach:

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

A co najważniejsze, możesz też mieszać i dopasowywać opisane wyżej strategie do różnych treści na stronie. Możesz na przykład opóźnić renderowanie tekstu w niektórych sekcjach do czasu, aż czcionka będzie dostępna, użyć czcionki zastępczej i ponownie przeprowadzić renderowanie po zakończeniu pobierania czcionki.

Odpowiednia pamięć podręczna to podstawa

Zasoby czcionek są zazwyczaj zasobami statycznymi, które nie są często aktualizowane. W związku z tym idealnie nadają się do długiego wygaśnięcia maksymalnego wieku – określ zarówno warunkowy nagłówek ETag, jak i optymalną zasadę Cache-Control dla wszystkich zasobów czcionek.

Jeśli Twoja aplikacja internetowa korzysta z skryptu service worker, w większości przypadków 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 ani IndexedDB. Każda z nich ma własny zestaw problemów z wydajnością. Pamięć podręczna HTTP przeglądarki zapewnia najlepszy i najbardziej niezawodny mechanizm dostarczania zasobów czcionek do przeglądarki.

Lista kontrolna ładowania 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óźnić renderowanie tekstu. Te funkcje platformy internetowej pozwalają zastąpić ten sposób działania w przypadku określonych czcionek oraz określić niestandardowe strategie renderowania i limitu czasu w przypadku różnych treści na stronie.
  • Określ 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 weryfikacji, co umożliwi wydajne wykorzystanie czcionek na różnych stronach. Jeśli używasz mechanizmu Service Worker, odpowiednia strategia jest ukierunkowana na pamięć podręczną.

Zautomatyzowane testowanie sposobu ładowania czcionek WebFont za pomocą Lighthouse

Narzędzie Lighthouse może zautomatyzować proces sprawdzania, czy jest zgodny ze sprawdzonymi metodami optymalizacji czcionek internetowych.

Możesz się upewnić, że Twoje strony są z czasem zgodne ze sprawdzonymi metodami optymalizacji czcionek internetowych: