By Spike Brehm
This post has been cross-posted on VentureBeat.
W Airbnb, wiele się nauczyliśmy w ciągu ostatnich kilku lat, budując bogate doświadczenia internetowe. W 2011 roku, wraz z naszą mobilną stroną internetową, wkroczyliśmy w świat aplikacji jednostronicowych, a od tego czasu uruchomiliśmy między innymi Listy Życzeń i naszą nowo zaprojektowaną stronę wyszukiwania. Każda z nich jest dużą aplikacją JavaScript, co oznacza, że większość kodu działa w przeglądarce, aby wspierać bardziej nowoczesne, interaktywne doświadczenie.
To podejście jest dziś powszechne, a biblioteki takie jak Backbone.js, Ember.js i Angular.js ułatwiły programistom budowanie tych bogatych aplikacji JavaScript. Stwierdziliśmy jednak, że tego typu aplikacje mają pewne krytyczne ograniczenia. Aby wyjaśnić dlaczego, najpierw zróbmy szybki objazd przez historię aplikacji sieciowych.
JavaScript dorasta
Od zarania sieci, przeglądanie stron działało w następujący sposób: przeglądarka żądała określonej strony (powiedzmy, „http://www.geocities.com/”), powodując, że serwer gdzieś w Internecie generował stronę HTML i wysyłał ją z powrotem przez kabel. To działało dobrze, ponieważ przeglądarki nie były zbyt potężne, a strony HTML reprezentowały dokumenty, które były w większości statyczne i samowystarczalne. JavaScript, stworzony, aby umożliwić stronom internetowym bycie bardziej dynamicznymi, nie pozwalał na wiele więcej niż pokazy slajdów i widżety do wybierania daty.
Po latach postępu w dziedzinie komputerów osobistych, kreatywni technolodzy popchnęli sieć do granic możliwości, a przeglądarki internetowe ewoluowały, aby dotrzymać im kroku. Teraz sieć dojrzała do w pełni funkcjonalnej platformy aplikacyjnej, a szybki JavaScript i standardy HTML5 umożliwiły programistom tworzenie bogatych aplikacji, które wcześniej były możliwe tylko na platformach natywnych.
Aplikacja jednostronicowa
Nie minęło wiele czasu, zanim programiści zaczęli budować całe aplikacje w przeglądarce przy użyciu JavaScript, korzystając z tych nowych możliwości. Aplikacje takie jak Gmail, klasyczny przykład aplikacji typu single-page, mogły natychmiast reagować na interakcje użytkownika, nie potrzebując już robić rundki do serwera tylko po to, by wyrenderować nową stronę.
Biblioteki takie jak Backbone.js, Ember.js i Angular.js są często określane jako biblioteki MVC (Model-View-Controller) lub MVVM (Model-View-ViewModel) po stronie klienta. Typowa architektura MVC po stronie klienta wygląda mniej więcej tak:
Większość logiki aplikacji (widoki, szablony, kontrolery, modele, internacjonalizacja, itp.) żyje w kliencie, a on rozmawia z API dla danych. Serwer może być napisany w dowolnym języku, takim jak Ruby, Python, czy Java, i głównie zajmuje się obsługą początkowej strony HTML. Po pobraniu plików JavaScript przez przeglądarkę, są one oceniane, a aplikacja po stronie klienta jest inicjalizowana, pobierając dane z API i renderując resztę strony HTML.
Jest to świetne dla użytkownika, ponieważ po wstępnym załadowaniu aplikacji, może ona obsługiwać szybką nawigację między stronami bez odświeżania strony, a jeśli jest zrobiona dobrze, może nawet pracować w trybie offline.
Jest to świetne rozwiązanie dla deweloperów, ponieważ wyidealizowana aplikacja jednostronicowa posiada wyraźne rozdzielenie obaw pomiędzy klientem a serwerem, promując przyjemny przepływ pracy i zapobiegając potrzebie dzielenia się zbyt dużą ilością logiki pomiędzy nimi, które często są napisane w różnych językach.
W praktyce jednak, istnieje kilka fatalnych wad tego podejścia, które uniemożliwiają jego zastosowanie w wielu przypadkach użycia.
SEO
Aplikacja, która może działać tylko po stronie klienta, nie może obsługiwać HTML dla robotów indeksujących, więc domyślnie będzie miała słabe SEO. Działanie crawlerów polega na wysyłaniu żądania do serwera WWW i interpretowaniu wyniku, ale jeśli serwer zwraca pustą stronę, nie ma to większej wartości. Istnieją obejścia, ale nie bez przeskakiwania przez pewne obręcze.
Wydajność
Przez ten sam znak, jeśli serwer nie renderuje pełnej strony HTML, ale zamiast tego czeka na JavaScript po stronie klienta, aby to zrobić, użytkownicy doświadczą kilku krytycznych sekund pustej strony lub ładowania spinnera przed zobaczeniem treści na stronie. Istnieje wiele badań pokazujących drastyczny wpływ powolnej strony na użytkowników, a tym samym na przychody. Amazon twierdzi, że każde 100ms redukcji czasu ładowania strony podnosi przychody o 1%. Twitter spędził rok i 40 inżynierów przebudowujących swoją stronę tak, aby renderowała się na serwerze zamiast na kliencie, twierdząc, że 5-krotna poprawa postrzeganego czasu ładowania.
Maintainability
Choć idealny przypadek może prowadzić do ładnej, czystej separacji obaw, nieuchronnie niektóre elementy logiki aplikacji lub logiki widoku kończą się duplikacją między klientem a serwerem, często w różnych językach. Powszechnymi przykładami są formatowanie daty i waluty, sprawdzanie poprawności formularzy i logika routingu. To sprawia, że konserwacja staje się koszmarem, szczególnie w przypadku bardziej złożonych aplikacji.
Niektórzy programiści, w tym ja, czują się ugryzieni przez to podejście – często dopiero po zainwestowaniu czasu i wysiłku w budowę aplikacji jednostronicowej staje się jasne, jakie są jej wady.
Podejście hybrydowe
Na koniec dnia tak naprawdę chcemy hybrydy nowego i starego podejścia: chcemy serwować w pełni sformatowany HTML z serwera dla wydajności i SEO, ale chcemy szybkości i elastyczności logiki aplikacji po stronie klienta.
W tym celu, eksperymentowaliśmy w Airbnb z aplikacjami „Isomorphic JavaScript”, czyli aplikacjami JavaScript, które mogą działać zarówno po stronie klienta, jak i po stronie serwera.
Aplikacja izomorficzna może wyglądać w ten sposób, nazwana tutaj „Client-server MVC”: