28 gru 2018
4 min

O server-side rendering w Angular

Jak rozpocząć pracę z server side rendering (SSR) w Angular? Na co uważać? Na te pytania odpowie nam Tomasz Borowski, trener szkoleń Angular in Space, którego zaprosiłem do wpisu gościnnego na moim blogu.

Autor Tomasz Borowski

Tomasz Borowski

Tomasz Borowski to frontend developer z 10 letnim doświadczeniem programistycznym, pracujący na co dzień przy implementacji złożonych aplikacji biznesowych w frameworku Angular. Od czasu do czasu występuje także jako prelegent na konferencjach międzynarodowych (w tym ngPoland, Agile Lean Europe) oraz lokalnych meetupach (w tym Angular Tricity, meet.js, dev.js). Od ponad dwóch lat prowadzi także serię warsztatów szkoleniowych Angular in Space.

Powrót do przeszłości?

Wiele lat temu, zanim podejście Single Page Application (SPA) stało się standardem w tworzeniu aplikacji webowych, mieliśmy do czynienia z aplikacjami, które w odpowiedzi na działanie użytkownika wysyłały gotowy do wyrenderowania w przeglądarce markup HTML. Taka forma komunikacji klient-serwer nie pozwalała na ponowne użycie wyświetlonych już fragmentów strony i sprawiała wrażenie wolniejszego działania, bo wymagała pełnego przeładowania strony.

Zastosowanie podejścia SPA pozwoliło na jednokrotne załadowanie do przeglądarki aplikacji webowej, która po uruchomieniu wiedziała “jak ma wyglądać i jak się ma zachowywać”. Dotychczasowa forma  komunikacji klient-serwer została uproszczona do zwykłej wymiany danych, najczęściej w oparciu o obiekty JSON. Aplikacje SPA sprawiały wrażenie szybszych i ładnie oddzielonych od technologii backendowych.

komunikacja klient-serwer

źródło: https://msdn.microsoft.com/en-us/magazine/dn463786.aspx

Dlaczego więc w ogóle rozważać renderowanie aplikacji po stronie serwera? Otóż duża ilość danych, jakie muszą zostać pobrane aby uruchomić aplikację SPA, wyrazie opóźnia dostępność aplikacji na wolniejszych urządzeniach lub tych korzystających ze słabego łącza internetowego. Również boty indeksujące strony internetowe mogą mieć problem z poprawnym indeksowaniem skomplikowanych aplikacji SPA.

Czy zatem da się połączyć zalety aplikacji SPA i generowania HTMLa po stronie serwera? Tak, a tworząc aplikację Angular możemy to łatwo zrobić z Angular Universal.

logo angular universal

Jak SSR działa w Angular?

Ideą server-side renderingu (SSR) w Angular jest szybkie zwrócenie przez serwer gotowego do wyrenderowania markupu HTML, podczas gdy aplikacja SPA będzie niezależnie pobierana w tle. Po ukończeniu tego pobierania, aplikacja zastępuje dotychczas wyrenderowany, statyczny HTML, oferując już pełne możliwości aplikacji.

Od strony technicznej będziemy mieli do czynienia z dwoma aplikacjami: nasza dotychczasowa aplikacja w Angular oraz Universal web server, który będzie odpowiedzialny za serwowanie assetów oraz wygenerowanie początkowego markupu HTML.

Diagram różnic Angular a Angular Universalźródło: https://medium.com/capital-one-tech/a-peek-into-the-open-source-technologies-behind-capitalone-com-80bae5ca9279

Jak wdrożyć SSR w aplikacji Angular?

Krok 1: Podążaj za Guide’m

Aby wdrożyć SSR w swojej aplikacji Angular zapoznaj się z oficjalnym Guide’m Angular Universal i wykonaj procedurę setupu krok po kroku. Jednakże jest parę spraw, o których warto dodatkowo pamiętać.

Krok 2: Blokuj warunkowo zapytania HTTP na starcie aplikacji

Kod odpowiedzialny za wywoływanie zapytań HTTP na starcie aplikacji może zostać wykonany dwukrotnie: w trakcie server-side renderingu oraz w przeglądarce podczas uruchamiania aplikacji Angular. Postaraj się wyeliminować to pierwsze wywołanie, gdyż może ono negatywnie wpłynąć na czas renderowania markupu HTML po stronie serwera. W tym celu można przygotować osobną konfigurację zmiennych środowiskowych w Angularze, dzięki której będziemy mogli blokować zapytania HTTP tylko w aplikacji renderowanej po stronie serwera.

import { environment } from '../environments/environment';

getArticles() {
   if (environment.ssr) {
     console.warn('Fetching articles is disabled');
     return of([]);
   }

   return this.http.get<Article[]>('/api/articles');
}

Krok 3: Przygotuj się na brak dostępności API przeglądarki

Podczas przygotowywania aplikacji do renderowania po stronie serwera pamiętaj, że nie będzie tam dostępne standardowe API przeglądarki. Jeśli korzystasz w aplikacji z obiektów window, document, localStorage itp. to będziesz musiał je zamockować (wykorzystać sztuczne / uproszczone obiekty). W tym celu możesz wykorzystać bibliotekę mock-browser.

const MockBrowser = require('mock-browser').mocks.MockBrowser;
const mock = new MockBrowser();
global['navigator'] = mock.getNavigator();
global['window'] = mock.getWindow();
global['document'] = mock.getDocument();
global['localStorage'] = global['window'].localStorage;

Mierzenie korzyści w praktyce

Warto zaznaczyć, że zalety stosowania SSR są słabo zauważalne na szybkich urządzeniach, dysponujących szybkim łączem internetowym. Aby sprawdzić, jak aplikacja ładuje się w przeglądarce w “nieco trudniejszych warunkach” otwórz Chrome Chrome Dev Tools, a następnie w zakładce network wybierz łącze “Slow 3G” i zaznacz “Disable cache”.

Dev tools - wyłączony cache

Po odświeżeniu okna przeglądarki będziesz mógł zaobserwować jak aplikacja jest ładowana. Zwróć uwagę, że już w odpowiedzi na pierwszy request przeglądarka otrzymuje markup HTML, który może wyrenderować i nie musi czekać na pobranie oraz uruchomienie całej aplikacji Angularowej.

Misja wprowadzenia do angular - preview

Aby zmierzyć korzyści z wdrożenia SSR w naszej aplikacji otwieramy Chrome Dev Tools na zakładce “Audits”. Interesuje nas audyt pod kątem “Performance” na symulowanym łączu “Fast 3G” i przy obniżonych parametrach CPU. Należy przeprowadzić taki sam audyt dla aplikacji korzystającej z SSR oraz dla wersji bez SSR. Dzięki temu będziemy mogli porównać wyniki i zauważyć korzyści server-side renderingu. Dla strony związanej ze szkoleniami Angular in Space audyt wykazał średnie skrócenie czasu pierwszego wyrenderowania zawartości strony z 4.1 sekund na 1.9 sekundy dla urządzeń mobilnych na łączu Fast 3G. Do testowania szybkości naszych web aplikacji możemy także wykorzystać takie narzędzia jak PageSpeed Insights czy Webpagetest.

Dane laboratyjne przy emulowanym połączeniu 3G

Wyniki testu PageSpeed Insights dla aplikacji bez SSR

Dane laboratyjne przy emulowanym połączeniu 3G

Wyniki testu PageSpeed Insights dla aplikacji z SSR

Podsumowanie

Server-side rendering z Angular Universal jest techniką przydatną w sytuacji, gdy chcemy szybciej dostarczyć początkową treść naszej strony na słabszych urządzeniach z wolniejszym dostępem do internetu. Dodatkową zaletą jest lepsza współpraca aplikacji z botami indeksującymi strony internetowe. Jednakże jeśli nie zależy nam na powyższych korzyściach, to SSR zdecydowanie nie jest nam niezbędny do życia 🙂

Najczęściej zadawane pytania

Jak działa server-side rendering (SSR) w Angular?

SSR w Angular generuje na serwerze początkowy markup HTML, który przeglądarka może wyświetlić, zanim pobierze i uruchomi aplikację SPA. Następnie aplikacja Angular ładuje się w tle i zastępuje statyczną treść, udostępniając pełną interaktywność. Za renderowanie HTML odpowiada serwer Angular Universal, który również serwuje zasoby aplikacji.

Jak przygotować aplikację Angular do SSR?

Aby wdrożyć SSR w aplikacji Angular, zacznij od wykonania kroków opisanych w oficjalnym przewodniku Angular Universal. Następnie sprawdź kod uruchamiany podczas startu aplikacji: zapytania HTTP mogą zostać wykonane zarówno przy renderowaniu na serwerze, jak i w przeglądarce. Uwzględnij też, że na serwerze nie są dostępne standardowe API przeglądarki.

Jak uniknąć podwójnych zapytań HTTP podczas SSR w Angular?

Podczas SSR zapytania HTTP wykonywane przy starcie mogą zostać wysłane ponownie po uruchomieniu aplikacji Angular w przeglądarce. Artykuł proponuje użycie osobnej konfiguracji środowiskowej, takiej jak environment.ssr, aby warunkowo pominąć pobieranie danych po stronie serwera. Może to skrócić czas generowania początkowego HTML; przykład zwraca pustą tablicę zamiast wysyłać żądanie.

Co zrobić z window, document i localStorage podczas SSR w Angular?

Kod SSR w Angular nie ma dostępu do standardowych obiektów przeglądarki, takich jak window, document czy localStorage. Jeśli aplikacja z nich korzysta, trzeba uwzględnić ich brak podczas renderowania po stronie serwera. W artykule pokazano użycie biblioteki mock-browser do utworzenia uproszczonych obiektów i przypisania ich do zmiennych globalnych.

Czy SSR w Angular poprawia SEO i szybkość ładowania strony?

SSR w Angular może szybciej dostarczyć początkową treść strony na słabszych urządzeniach i wolniejszych łączach, a także ułatwić indeksowanie aplikacji przez boty. Korzyści warto zmierzyć, porównując wersję z SSR i bez niego przy tych samych warunkach sieci oraz CPU. W opisanym audycie mobilnym czas pierwszego renderowania skrócił się średnio z 4,1 do 1,9 sekundy.

Podziel się artykułem

Zapisz się na nasz newsletter

Dołącz do community Angular.love i bądź na bieżąco z trendami.