Optymalizacja obrazów zgodnie z dyrektywą Angular Image

Kara Erickson
Kara Erickson
Leena Sohoni
Leena Sohoni

W maju 2022 r. zespoły Aurora i Angular ogłosiły, że nawiążą współpracę nad dyrektywą dotyczącą obrazów dla Angular. Dyrektywa została niedawno opublikowana w wersji deweloperskiej Angular w wersji 14.2. Z tego posta dowiesz się, jak nowa dyrektywa dotycząca obrazów, NgOptimizedImage, obsługuje optymalizację obrazów w Angular.

Wprowadzenie

Obrazy to powszechny i istotny element wrażeń użytkowników – 99, 9% stron internetowych generuje żądania dotyczące co najmniej jednego obrazu. Obrazy mają również największy wpływ na wielkość strony – jej mediana to 982 kilobajty na stronę.

Obrazy mogą zmniejszać wydajność stron internetowych i mieć wpływ na dane Podstawowych wskaźników internetowych ze względu na rosnącą liczbę i rozmiary obrazów. W przypadku 79, 4% stron na komputery w 2021 roku element największego wyrenderowania treści (LCP) był elementem największego wyrenderowania treści. Dla wielu z nas wyszukiwanie zoptymalizowanych obrazów stało się nieustannym wysiłkiem.

Zespół Aurora wierzy, że wykorzystanie potencjału platform do dostarczania wbudowanych rozwiązań typowych problemów programistów. Pierwszą rzeczą, którą skorzystali z optymalizacji obrazów, był komponent obrazu Next.js. Zespół uznał ten komponent za pole do testowania, czy ulepszenie optymalizacji obrazów dla programistów (DX) może przełożyć się na wzrost wydajności większej liczby aplikacji korzystających z platform.

Pierwsze wyniki uzyskane przez użytkownika Next.js, Leboncoin, były zachęcające. Po wprowadzeniu next/image firma Leboncoin odnotowała znaczny wzrost LCP (z 2,4 s do 1,7 s). Kolejne wdrożenie next/image w społeczności odegrało rolę w zwiększeniu liczby źródeł Next.js, które osiągnęły progi LCP. Wkrótce pojawiły się prośby o udostępnienie podobnych funkcji na innych platformach – jedną z nich jest Angular.

Dlatego zespół Aurora skonsultował się z firmami Angular i Nuxt, aby stworzyć prototyp komponentów graficznych na potrzeby tych platform. Komponent obrazu Nuxt został wprowadzony w zeszłym roku. Teraz opublikowaliśmy dyrektywę Angular dotyczącą obrazu (NgOptimizedImage), która przenosi wartości domyślne optymalizacji obrazów do Angular.

Szansa

Angular to jedna z najpopularniejszych platform JavaScriptu używanych obecnie przez programistów. Jest używana przez ponad 50 tys. źródeł indeksowanych przez HTTPArchive na urządzeniach mobilnych i może być pobierana z NPM niemal 3 miliony tygodniowo.

LCP witryn Angular w ciągu ostatniego roku.

Jeśli przyjrzymy się wynikom w podstawowych wskaźnikach internetowych, odsetek źródeł Angular, które osiągają „dobre” progi LCP, nadal wymaga dopracowania. Tylko 18,74% witryn Angular miało w czerwcu 2022 r.dobre wartości LCP na urządzeniach mobilnych. Obrazy stanowią element LCP ponad 70% stron internetowych na urządzeniach mobilnych i komputerach, więc niezoptymalizowane obrazy LCP mogą być jedną z najczęstszych przyczyn niskiej wartości LCP w witrynach Angular.

Dyrektywa Angular dotycząca obrazów została opracowana, aby pomóc w zwiększeniu tych wartości.

Minimalna wersja dyrektywy NgOptimizedImage

Minimalistyczna dyrektywa dotycząca obrazów w Angular opiera się na doświadczeniach z dotychczasowych komponentów obrazów, które Aurora zbudowała, i jednocześnie dostosowuje projekt do sposobu renderowania po stronie klienta w Angular. Wiele standardowych problemów z optymalizacją obrazów zostało rozwiązanych przez:

  • Określenie silnych ustawień domyślnych.
  • zgłaszanie błędów lub ostrzeżeń, aby zapewnić zgodność ze sprawdzonymi metodami;

Najważniejsze cechy nowego interfejsu:

  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 karuzeli), powinny być wczytywane leniwie. Leniwe ładowanie pozwala zwolnić zasoby przeglądarki, aby móc wczytać inny krytyczny tekst, multimedia lub skrypty. Większość obrazów nie ma krytycznego znaczenia i powinna być leniwie ładowana, ale w 2021 roku tylko 7,8% stron korzystało z natywnego leniwego ładowania.

    Dyrektywa Angular dotycząca obrazów domyślnie wczytuje niekrytyczne obrazy i z zainteresowaniem wczytuje tylko te obrazy oznaczone jako priority. Dzięki temu większość obrazów będzie prawidłowo się ładować.

  2. Priorytetowe traktowanie najważniejszych obrazów

    Dodawanie wskazówek dotyczących zasobów (np. preload lub preconnect), aby priorytetowo traktować wczytywanie kluczowych obrazów, jest zalecaną sprawdzoną metodą. Jednak większość aplikacji ich nie używa. Według raportu Web Almanac z 2021 roku tylko 12,7% stron mobilnych korzysta ze wskazówek związanych z wcześniejszym połączeniem, a tylko 22,1% stron mobilnych korzysta ze wskazówek wstępnego wczytywania.

    Dyrektywa image działa na 2 przód, gdy obrazy są oznaczane jako priorytetowe.

    • Ustawia fetchPriority na "high", by przeglądarka wie, że powinna pobrać obraz o wysokim priorytecie.
    • W trybie programowania kontrola w czasie działania potwierdza, że została dołączona wskazówka na temat zasobu preconnect odpowiadająca źródłom obrazu.

    W trybie programistycznym dyrektywa używa też interfejsu PerformanceObserver API, aby sprawdzać, czy obraz LCP został oznaczony jako priority zgodnie z oczekiwaniami. Jeśli identyfikator nie jest oznaczony jako priority, zgłaszany jest błąd, co powoduje, że deweloper ma dodać atrybut priority do obrazu LCP.

    W efekcie dzięki tej kombinacji automatyzacji i zgodności obraz LCP ma wskazówkę preconnect, atrybut fetchpriority o wartości high i nie jest leniwie ładowany.

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

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

    Dyrektywa zachęca do korzystania z graficznych sieci CDN, ponieważ ich konfigurowanie w aplikacji jest wyjątkowo atrakcyjne dla programistów. Obsługuje ona interfejs API wczytywania, który pozwala zdefiniować dostawcę CDN i podstawowy adres URL w konfiguracji. Po skonfigurowaniu zasobu musisz tylko podać w znacznikach nazwę zasobu. Na przykład

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

    Jest to równoważne z dodaniem 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 udostępnia wbudowane moduły ładujące z optymalną konfiguracją najpopularniejszych sieci CDN z obrazami. Te moduły automatycznie sformatują adresy URL obrazów, aby mieć pewność, że w każdej sieci CDN są używane zalecany format obrazu i ustawienia kompresji.

  4. Wbudowane błędy i ostrzeżenia

    Oprócz wymienionych wyżej wbudowanych optymalizacji dyrektywa ma też wbudowane funkcje kontrolne, które pozwalają sprawdzić, czy deweloperzy przestrzegają zalecanych sprawdzonych metod w przypadku znaczników obrazów. Dyrektywa dotycząca obrazu wykonuje te testy.

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

    2. Współczynnik proporcji: dyrektywa dotycząca obrazu zgłasza błąd, aby poinformować programistów, że współczynnik proporcji elementu width:height zdefiniowanego w kodzie HTML nie jest zbliżony do rzeczywistego współczynnika proporcji renderowanego obrazu. Może to spowodować zniekształcenia obrazu na ekranie. Może się tak zdarzyć, jeśli

      1. Nieprawidłowe wymiary (szerokość lub wysokość) przez pomyłkę lub
      2. Jeśli jeden wymiar jest zdefiniowany w pliku CSS jako wartość procentowa, a drugi nie (np. funkcja width: 100% wymaga parametru height: auto, aby zapewnić powiększanie obrazu w obu wymiarach).
    3. Obrazy ponadwymiarowe: jeśli obraz nie ma zdefiniowanej wartości srcset, a rzeczywisty obraz jest znacznie większy niż renderowany obraz, dyrektywa wyświetli ostrzeżenie zalecające użycie atrybutów srcset i sizes.

    4. Gęstość obrazu: gdy spróbujesz uwzględnić w elemencie srcset obraz o gęstości pikseli większej niż 3x, dyrektywa spowoduje błąd. Ogólnie nie zalecamy używania deskryptorów większych niż 2x, ponieważ ma to niezamierzone konsekwencje zmuszania urządzeń mobilnych o wysokiej rozdzielczości do pobierania dużych obrazów. Co więcej, ludzkie oko nie zauważa znaczącej różnicy powyżej 2x.

Testy

Głównym wyzwaniem podczas projektowania usługi NgOptimizedImage było dostosowanie strategii optymalizacji obrazów pod kątem współpracy z klientami. Domyślnym sposobem renderowania w Next.js jest renderowanie po stronie serwera (SSR) lub statyczne generowanie witryny (SSG), a w Angular – renderowanie po stronie klienta. Chociaż Angular obsługuje bibliotekę SSR – angular/Universal – większość aplikacji Angular (około 60%) używa żądania podpisania certyfikatu.

Dyrektywa dotycząca obrazu została w całości opracowana z myślą o przedstawicielach ds. obsługi klienta (CSR), aby dostosować ją do typowego przypadku użycia w aplikacjach Angular. W takiej sytuacji zespół nałożył dodatkowe ograniczenia i musiał się zastanowić, jak opracować konkretne optymalizacje dla aplikacji CSR.

Oto niektóre z napotkanych wyzwań:

  1. Wskazówki dotyczące zasobów

    Wstępne wczytywanie kluczowych zasobów ułatwia przeglądarce wykrycie ich wcześniej. Jednak uwzględnianie wskazówek dotyczących zasobów w aplikacjach Angular jest skomplikowane, ponieważ:

    Ręczne dodawanie: deweloperzy mają trudności z ręcznym dodawaniem wskazówek dotyczących zasobów preload. Angular używa jednego udostępnionego pliku index.html dla całego projektu lub wszystkich tras w witrynie. Dzięki temu pole <head> dokumentu jest takie samo dla każdej trasy (przynajmniej w momencie wyświetlenia). Dodanie dowolnej wskazówki preload do elementu <head> spowoduje, że zasób będzie wstępnie wczytywany na potrzeby wszystkich tras, nawet jeśli nie jest wymagany. Dlatego nie zalecamy ręcznego dodawania wskazówek preload.

    Automatyczne dodawanie podczas renderowania: użycie platformy do dodawania wskazówek wstępnego wczytywania do nagłówka dokumentu podczas renderowania w aplikacji CSR nie pomaga. Renderowanie odbywa się po pobraniu i wykonaniu JavaScriptu, więc interfejs <head> będzie renderowany zbyt późno, aby miał jakąkolwiek wartość.

    W pierwszej wersji dyrektywy połączenie wskazówek preconnect i fetchpriority określa priorytet obrazu zamiast preload. Aurora współpracuje obecnie z zespołem Angular CLI nad włączeniem automatycznego wstrzykiwania wskazówek dotyczących zasobów w momencie kompilacji. Więcej informacji już wkrótce.

  2. Optymalizowanie rozmiaru i formatu obrazu na serwerze

    Aplikacje Angular są zwykle renderowane po stronie klienta, więc obrazy w systemie plików nie mogą być kompresowane na żądanie i są wyświetlane w niezmienionej formie. Z tego powodu zalecamy korzystanie z sieci CDN obrazów, aby skompresować obrazy i przekonwertować je na nowoczesne formaty, takie jak WebP lub AVIF.

    Chociaż dyrektywa nie wymusza używania obrazów CDN, zdecydowanie zalecamy używanie ich razem z dyrektywą, a jej wbudowane moduły ładowania zapewniają wybór prawidłowych opcji konfiguracyjnych.

Wpływ

Poniższy przykład pokazuje różnicę między dyrektywą dotyczącą obrazów w Angular a wydajnością obrazów. Porównuje on 2 witryny:

Witryna 1: wykorzystuje natywne elementy <img> z obrazami wyświetlanymi przez sieć CDN firmy Imgix (z domyślnymi opcjami konfiguracji).

Witryna 2: w przypadku wszystkich obrazów użyj dyrektywy dotyczącej obrazu. Zawiera również optymalizacje zalecane bezpośrednio w wyniku ostrzeżeń lub błędów spowodowanych przez dyrektywę.

Porównanie paska zdjęć: witryna 1 z natywnymi tagami obrazów oraz strona 2 z dyrektywą dotyczącą obrazów w Angular.

Zespół współpracował z partnerami, aby sprawdzić wpływ dyrektywy dotyczącej obrazu na wydajność rzeczywistych aplikacji Angular dla firm.

Jednym z takich partnerów był Land's End. Spodziewano się, że ich witryna będzie dobrym przykładem testowania wyników, które mogą zobaczyć prawdziwe aplikacje.

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

Plan na przyszłość

To tylko pierwsza część projektu dyrektywy dotyczącej obrazów w Angular. W przyszłych wersjach planujemy wprowadzić wiele innych funkcji. Oto niektóre z nich:

  • Lepsza obsługa obrazów elastycznych:

    NgOptimizedImage obecnie obsługuje używanie srcset, ale atrybuty srcset i sizes trzeba podać ręcznie w przypadku każdego zdjęcia. W przyszłości dyrektywa może automatycznie generować atrybuty srcset i sizes.

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

    Może istnieć możliwość integracji z interfejsem wiersza poleceń Angular w celu generowania tagów wstępnego połączenia i wstępnego wczytywania dla krytycznych obrazów LCP.

  • Obsługa Angular SSR

    Wersja MVP została opracowana z uwzględnieniem ograniczeń Angular CSR, ale warto też zapoznać się z rozwiązaniami do optymalizacji obrazów w Angular SSR (Angular/Universal).

  • Ulepszenia interfejsu dla deweloperów

    NgOptimizedImage wymaga określenia atrybutów width i height dla każdego obrazu. Jednak określenie ich dla każdego obrazu może być uciążliwe dla niektórych programistów. Możesz poprawić wrażenia programistów w kolejnej iteracji:

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

Podsumowanie

Dyrektywa w języku Angular będzie udostępniana deweloperom etapami, począwszy od wersji testowej dla programistów w wersji 14.2.0. Wypróbuj usługę NgOptimizedImage i podziel się opinią.

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