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.
Tło
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 środowiska dla programistów (DX) w zakresie optymalizacji obrazów może poprawić wydajność 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.
Możliwość
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.
Jeśli spojrzymy na wyniki podstawowych wskaźników internetowych, odsetek źródeł Angular spełniających „dobre” Musisz jeszcze poprawić progi LCP. 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:
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ć.Priorytetowe traktowanie najważniejszych obrazów
Dodawanie wskazówek dotyczących zasobów (np.
preload
lubpreconnect
), aby nadawać priorytet wczytywaniu krytycznych obrazów, zalecana sprawdzona metoda. 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 programisty 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 jakopriority
, generowany jest błąd, co powoduje, że deweloper ma dodać atrybutpriority
do obrazu LCP.W efekcie dzięki tej kombinacji automatyzacji i zgodności obraz LCP ma wskazówkę
preconnect
, atrybutfetchpriority
o wartościhigh
i nie jest leniwie ładowany.- Ustawia fetchPriority na
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, dzięki czemu ich konfiguracja w aplikacji jest wyjątkowo atrakcyjna dla programistów. Obsługuje 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.
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.
Obrazy bez rozmiaru: dyrektywa dotycząca obrazu 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, wpływając na wartość CLS (skumulowane przesunięcie układu) strony. Aby temu zapobiec, najlepiej jest określić atrybuty
width
iheight
.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:- Nieprawidłowe wymiary (szerokość lub wysokość) przez pomyłkę lub
- Jeśli jeden wymiar jest zdefiniowany w pliku CSS jako wartość procentowa, a drugi nie (np. funkcja
width: 100%
wymaga parametruheight: auto
, aby zapewnić powiększanie obrazu w obu wymiarach).
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ówsrcset
isizes
.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.
Wyzwania
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ń:
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ówkipreload
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ówekpreload
.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
ifetchpriority
określa priorytet obrazu zamiastpreload
. 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.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. Dlatego zalecamy korzystanie z sieci CDN dla obrazów, by skompresować obrazy i przekonwertować je na nowoczesne formaty, takie jak WebP czy 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ę.
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żywaniesrcset
, ale atrybutysrcset
isizes
trzeba podać ręcznie w przypadku każdego zdjęcia. W przyszłości dyrektywa może automatycznie generować atrybutysrcset
isizes
.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ówwidth
iheight
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:- 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. - Użycie integracji interfejsu wiersza poleceń do automatycznego ustawiania szerokości i wysokości obrazów lokalnych na podstawie rzeczywistych wymiarów obrazu.
- Obsługuje dodatkowy tryb (podobny do opcji układu 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.