Optymalizacja obrazów zgodnie z dyrektywą Angular Image

Karolina Eryk
Kara Erickson
Lena Sohoni
Leena Sohoni

W maju 2022 roku zespoły Aurora i Angular ogłosiły, że nawiążą współpracę nad dyrektywą dotyczącą obrazów dla Angular. Dyrektywa została niedawno udostępniona w wersji testowej dla programistów w ramach Angular w wersji 14.2. Ten post zawiera informacje o tym, jak nowa dyrektywa w sprawie obrazu, NgOptimizedImage, obsługuje optymalizację obrazów w Angular.

Wprowadzenie

Obrazy są częstym i istotnym elementem doświadczeń użytkowników internetu, przy czym 99,9% stron internetowych generuje żądania co najmniej jednego obrazu. Obrazy mają też największy wpływ na wielkość strony – jej mediana to 982 kilobajty na stronę.

Ze względu na rosnącą liczbę i rozmiar obrazów obrazy mogą zmniejszać wydajność stron internetowych i wpływać na podstawowe wskaźniki internetowe. W 2021 roku w przypadku 79, 4% stron na komputery obraz był elementem największego wyrenderowania treści (LCP). Dążenie do zoptymalizowania obrazów stało się dla wielu nas stałym wyzwaniem.

Zespół Aurora wierzy, że wykorzystywany jest potencjał platform, dzięki czemu mogą stworzyć wbudowane rozwiązania typowych problemów dla programistów. Pierwszym wyzwaniem w zakresie optymalizacji obrazów był komponent obrazu Next.js. Uznali, że ten komponent służy do testowania, czy poprawa wrażeń programistów w zakresie optymalizacji obrazów może przełożyć się na wzrost wydajności w przypadku większej liczby aplikacji korzystających z platform.

Pierwszy zestaw wyników z Next.js, Leboncoin, był bardzo ciekawy. Po rozpoczęciu korzystania z next/image firma Leboncoin odnotowała znaczny wzrost LCP (z 2,4 do 1,7 s). Późniejsze wdrożenie w społeczności next/image środowiska wykonawczego pomogło zwiększyć liczbę źródeł Next.js, które osiągnęły wartości progowe LCP. Wkrótce pojawiły się prośby o podobne funkcje w innych usługach. Jednym z nich był Angular.

Dlatego skonsultowała się z firmą Angular i Nuxt, aby utworzyć prototypy komponentów obrazów dla tych platform. Komponent z obrazem Nuxt został wprowadzony w zeszłym roku. Udostępniliśmy dyrektywę w postaci obrazu Angular (NgOptimizedImage), aby umożliwić korzystanie z domyślnych ustawień optymalizacji obrazów w Angular.

Opportunity

Angular to jedna z najważniejszych platform JavaScriptu używanych dziś przez programistów. Jest używane przez ponad 50 tys. źródeł zindeksowanych przez HTTPArchive na urządzeniach mobilnych i ma prawie 3 miliony pobrań tygodniowo w NPM.

LCP dla witryn Angular w ciągu ostatniego roku.

Jeśli chodzi o wyniki dotyczące podstawowych wskaźników internetowych, odsetek źródeł z Angular, które spełniają „dobre” wartości progowe LCP, nadal wymaga dopracowania. W czerwcu 2022 r.tylko 18,74% witryn Angular miało dobry wskaźnik LCP dla urządzeń mobilnych. Ponieważ obrazy stanowią element LCP w przypadku ponad 70% stron na urządzenia mobilne i komputery, niezoptymalizowane obrazy LCP mogą być jedną z głównych przyczyn niskiej wartości LCP w witrynach Angular.

Dyrektywa w sprawie obrazów w Angular została opracowana, aby pomóc zwiększyć te liczby.

MVP dyrektywy NgOptimizedImage

Minimalna wersja produktu dyrektywy Angular opiera się na komponentach obrazów stworzonych przez Aurora i dostosowanym do sposobu renderowania po stronie klienta w Angular. Wiele standardowych problemów z optymalizacją obrazów zostało rozwiązanych przez:

  • Udostępnianie silnych wartości domyślnych.
  • Zgłaszanie błędów lub ostrzeżeń w celu zapewnienia zgodności ze sprawdzonymi metodami.

Oto najważniejsze cechy projektu:

  1. Inteligentne leniwe ładowanie

    Obrazy, które są niewidoczne dla użytkownika podczas wczytywania strony (np. obrazy w części strony widocznej po przewinięciu lub ukryte obrazy w formie karuzeli), powinny być leniwie ładowane. Leniwe ładowanie pozwala wykorzystać zasoby przeglądarki do ładowania innych kluczowych tekstów, multimediów lub skryptów. Większość obrazów nie jest krytyczna i powinna być leniwie ładowane, ale w 2021 roku tylko 7,8% stron korzystało z natywnego leniwego ładowania.

    Leniwa dyrektywa w sprawie obrazów w Angular domyślnie wczytuje obrazy niekrytyczne i z łatwością wczytuje tylko obrazy oznaczone jako priority. Zapewnia to optymalne działanie większości obrazów.

  2. Priorytetowe traktowanie najważniejszych obrazów

    Dodawanie wskazówek dotyczących zasobów (np. preload lub preconnect), aby nadać priorytet ładowaniu najważniejszych obrazów, jest zalecaną sprawdzoną metodą. Większość aplikacji z nich nie korzysta. Według raportu Web Almanac z 2021 r. tylko 12,7% stron mobilnych korzysta ze wskazówek dotyczących wstępnego łączenia, a tylko 22,1% stron mobilnych korzysta ze wskazówek wstępnego wczytywania.

    Dyrektywa dotycząca obrazów działa na dwóch frontach, gdy obrazy są oznaczone jako priorytetowe.

    • Ustawia ona priorytet pobierania obrazu na "high", aby przeglądarka wiedziała, że ma pobrać obraz z wysokim priorytetem.
    • W trybie deweloperskim sprawdzanie w czasie działania potwierdza, że dołączono wskazówkę dotyczącą zasobu preconnect odpowiadającej pochodzeniu obrazu.

    W trybie deweloperskim dyrektywa używa też interfejsu PerformanceObserver API do sprawdzania, czy obraz LCP został oznaczony jako priority zgodnie z oczekiwaniami. Jeśli nie jest oznaczony jako priority, zgłaszany jest błąd i instrukcja dla programisty, aby dodał atrybut priority do obrazu LCP.

    Dzięki temu połączenie automatyzacji i zgodności zapewnia, że obraz LCP będzie miał wskazówkę preconnect, wartość atrybutu fetchpriority o wartości high i nie będzie leniwy.

  3. Zoptymalizowana konfiguracja pod kątem popularnych narzędzi do obsługi obrazów

    Zalecamy, aby aplikacje Angular korzystały z sieci CDN z obrazami, które często domyślnie zapewniają usługi optymalizacji.

    Zgodnie z dyrektywą zachęcamy do korzystania z sieci CDN na potrzeby obrazów ze względu na możliwość ich konfiguracji w aplikacji w wyjątkowo atrakcyjny sposób. Obsługuje ona interfejs wczytujący interfejs API, który umożliwia zdefiniowanie dostawcy CDN i podstawowego adresu URL w konfiguracji. Gdy to zrobisz, wystarczy podać nazwę zasobu w znacznikach. Przykład:

    // in module providers:
    provideImgixLoader('https://mysite.net/assets/')
    
    // in markup
    <img ngSrc="image.png" >
    <img ngSrc="image2.png" >
    

    Jest to równoznaczne z uwzględnieniem poniższych tagów graficznych i zmniejsza liczbę znaczników, które programiści muszą dodawać do każdego obrazu.

    <img src="https://mysite.net/assets/image.png">
    <img src="https://mysite.net/assets/image2.png">
    

    Dyrektywa dotycząca obrazów zapewnia wbudowane moduły ładowania o optymalnej konfiguracji dla najpopularniejszych sieci CDN na potrzeby obrazów. Te moduły automatycznie formatują adresy URL obrazów, aby zapewnić stosowanie zalecanego formatu obrazu i ustawień kompresji dla każdej sieci CDN.

  4. Wbudowane błędy i ostrzeżenia

    Oprócz powyższych wbudowanych optymalizacji dyrektywa zawiera też wbudowane mechanizmy kontroli, dzięki którym deweloperzy przestrzegają zalecanych sprawdzonych metod dotyczących znaczników obrazów. Dyrektywa dotycząca obrazu wykonuje podane niżej testy.

    1. Obrazy bez określonego rozmiaru: dyrektywa dotycząca grafiki zgłasza błąd, jeśli znaczniki obrazu nie mają określonej szerokości i wysokości. Obrazy bez rozmiaru mogą powodować przesunięcia układu, co wpływa na dane skumulowane przesunięcie układu (CLS). Aby temu zapobiec, najlepiej jest określić atrybuty width i height.

    2. Współczynnik proporcji: dyrektywa dotycząca grafiki zwraca błąd, który informuje programistów, jeśli współczynnik proporcji obrazu width:height zdefiniowany w kodzie HTML nie odpowiada rzeczywistemu formatowi renderowanego obrazu. Może to spowodować zniekształcenie obrazu na ekranie. Może się tak zdarzyć, jeśli

      1. zdefiniowano nieprawidłowe wymiary (szerokość lub wysokość) przez pomyłkę lub
      2. Jeśli jeden wymiar jest zdefiniowany w procentach, a drugi nie (np. width: 100% potrzebuje parametru height: auto, aby zapewnić, że obraz będzie rozwinął się w obu wymiarach).
    3. Ponadwymiarowe obrazy: jeśli atrybut srcset nie jest zdefiniowany, a obraz wewnętrzny jest znacznie większy od renderowanego obrazu, dyrektywa wyświetli ostrzeżenie sugerujące użycie atrybutów srcset i sizes.

    4. Gęstość obrazu: dyrektywa zgłosi błąd, jeśli w komponencie srcset spróbujesz umieścić obraz o gęstości większej niż 3x. Opisy wyższe niż 2x zwykle nie są zalecane, ponieważ powoduje to wymuszenie pobierania dużych obrazów na urządzenia mobilne o wysokiej rozdzielczości. Co więcej, ludzkie oko nie jest w stanie powiedzieć więcej niż 2 razy więcej.

Wyzwania

Dostosowanie strategii optymalizacji obrazów do potrzeb klienta w ramach struktury po stronie klienta było głównym wyzwaniem podczas projektowania usługi NgOptimizedImage. Domyślnym sposobem renderowania w Next.js jest renderowanie po stronie serwera (SSR) lub static Site Generation (SSG), a w Angular renderowanie po stronie klienta (CSR). Mimo że Angular obsługuje bibliotekę SSR – Angular/Universal – większość aplikacji Angular (ok. 60%) używa żądań CSR.

Dyrektywa dotycząca obrazów została stworzona w całości z myślą o osobach odpowiedzialnych za obsługę klienta i dostosowuje się do typowych zastosowań w aplikacjach Angular. Wiązało się to z dodatkowymi ograniczeniami, a zespół musiał ponownie się zastanowić, jak opracować konkretne optymalizacje dla aplikacji dla obsługi klienta.

Oto niektóre z napotkanych problemów:

  1. Pomocne wskazówki dotyczące zasobów

    Wstępne wczytywanie najważniejszych zasobów pomaga przeglądarce wykryć je wcześniej. Podawanie wskazówek dotyczących zasobów w aplikacjach Angular jest jednak skomplikowane, ponieważ:

    Dodawanie ręczne: programiści mają kłopoty z ręcznym dodawaniem podpowiedzi dotyczącej zasobów preload. Angular używa jednego udostępnionego pliku index.html dla całego projektu lub wszystkich tras w witrynie. Dlatego <head> dokumentu jest taki sam dla każdej trasy (przynajmniej w czasie wyświetlania). Dodanie jakiejkolwiek wskazówki preload do elementu <head> spowoduje, że zasób zostanie wstępnie wczytany na wszystkich trasach, nawet jeśli nie jest wymagany. Dlatego nie zalecamy ręcznego dodawania wskazówek preload.

    Automatyczne dodawanie podczas renderowania: Użycie platformy do dodania do nagłówka dokumentu wskazówek wczytywanego wstępnie do nagłówka dokumentu podczas renderowania w aplikacji z żądaniem podpisania certyfikatu nie pomaga. Renderowanie odbywa się po pobraniu i wykonaniu JavaScriptu, więc <head> będzie renderowany za późno, aby nie miał żadnej wartości.

    W pierwszej wersji dyrektywy zamiast preload służy kombinacja wskazówek preconnect i fetchpriority. Jednak zespół Aurora współpracuje obecnie z zespołem interfejsu wiersza poleceń Angular, aby umożliwić automatyczne wstrzykiwanie wskazówek dotyczących zasobów podczas kompilacji. Więcej informacji już wkrótce.

  2. Optymalizowanie rozmiaru i formatu obrazu na serwerze

    Aplikacje Angular są zwykle renderowane po stronie klienta, dlatego obrazów w systemie plików nie można skompresować w czasie żądania. Z tego powodu zalecamy korzystanie z sieci CDN z obrazami, aby kompresować obrazy i konwertować je na nowoczesne formaty, takie jak WebP lub AVIF.

    Chociaż ta dyrektywa nie wymusza korzystania z sieci CDN na potrzeby obrazów, zdecydowanie zalecamy stosowanie ich wraz z tą dyrektywą, a jej wbudowane moduły wczytywania zapewniają, że stosowane są prawidłowe opcje konfiguracji.

Wpływ

Poniższy przykład pokazuje różnicę w wydajności obrazu przez dyrektywę Angular dotyczącą obrazów. Narzędzie porównuje 2 witryny:

Witryna 1: używa natywnych elementów <img> z obrazami udostępnianymi przez CDN Imgix (z domyślnymi opcjami konfiguracji).

Witryna druga: użyj dyrektywy dotyczącej wszystkich obrazów. Obejmuje też optymalizacje zalecane bezpośrednio przez ostrzeżenia lub błędy zgłaszane przez dyrektywę.

Porównanie paska zdjęć: witryna pierwsza z natywnymi tagami graficznymi i witryna druga z dyrektywą Angular dotyczącą obrazów.

Zespół we współpracy z partnerami zweryfikował wpływ dyrektywy dotyczącej obrazów na wydajność rzeczywistych aplikacji Angular dla firm.

Jednym z tych partnerów był Land's End. Spodziewano się, że witryna sprawdzi się jako dobry przypadek do testowania wyników, które mogą zobaczyć rzeczywiste aplikacje.

Testy laboratoryjne Lighthouse zostały przeprowadzone w środowisku kontroli jakości przed użyciem dyrektywy dotyczącej obrazów i po jej zastosowaniu. Na komputerach mediana LCP spadła z 12,0 do 3,0 s, co stanowi wzrost o 75%. W przypadku urządzeń mobilnych mediana LCP spadła z 20,2 do 12,0 s (poprawa o 40,6%).

Plan działań na przyszłość

To dopiero pierwsza część projektu dyrektywy Angular dotyczącej obrazów. W przyszłych wersjach planujemy wprowadzić wiele innych funkcji, takich jak:

  • Lepsza obsługa obrazów elastycznych:

    NgOptimizedImage obecnie obsługuje atrybuty srcset, ale atrybuty srcset i sizes trzeba podać ręcznie dla każdego obrazu. W przyszłości dyrektywa może automatycznie generować atrybuty srcset i sizes.

  • Automatyczne wstrzykiwanie wskazówek dotyczących zasobów

    Integracja z interfejsem wiersza poleceń Angular może umożliwić wygenerowanie wstępnego połączenia i wstępnego wczytywania tagów dla krytycznych obrazów LCP.

  • Obsługa Angular SSR

    Wersja MVP została opracowana z myślą o ograniczeniach Angular CSR, ale należy również poznać rozwiązania do optymalizacji obrazów dla Angular SSR (Angular/uniwersalne).

  • Ulepszenia interfejsu dla programistów

    NgOptimizedImage wymaga określenia atrybutów width i height dla każdego obrazu. Określenie tych wartości dla poszczególnych obrazów może być jednak uciążliwe dla niektórych programistów. W następnej iteracji można poprawić wygodę deweloperów:

    1. Obsługuje dodatkowy tryb (podobny do opcji układu obrazu w Next.js typu „fill”), który nie wymaga wyraźnego określenia szerokości ani wysokości.
    2. Użycie integracji interfejsu wiersza poleceń w celu automatycznego ustawiania szerokości i wysokości obrazów lokalnych przez określenie rzeczywistych wymiarów obrazu.

Podsumowanie

Dyrektywa w sprawie obrazu w Angular będzie udostępniana stopniowo, począwszy od wersji przedpremierowej w wersji 14.2.0 dla programistów. Wypróbuj usługę NgOptimizedImage i podziel się opinią.

Specjalne podziękowania dla Katie Hempenius i Alexa Castle'a za ich wkład.