Jest rok 2020. Twój zespół coraz bardziej skłania się ku tworzeniu aplikacji jednostronicowych lub przynajmniej włączaniu bogatych komponentów do zwykłych aplikacji wielostronicowych. [GraphQL](https://graphql.org/) ma już [ponad dwa lata](https://en.wikipedia.org/wiki/GraphQL), co według standardów ekosystemu JavaScript można uznać za dojrzałe. Mieliśmy ochotę na odrobinę przygody, więc zrezygnowaliśmy z typowych interfejsów API JSON i od razu wkroczyliśmy do akcji - oto, czego się nauczyliśmy.
Jest rok 2020. Twój zespół coraz bardziej skłania się ku tworzeniu aplikacji jednostronicowych lub przynajmniej włączaniu bogatych komponentów do zwykłych aplikacji wielostronicowych. [GraphQL](https://graphql.org/) ma już [ponad dwa lata](https://en.wikipedia.org/wiki/GraphQL), co według JavaScript standardy ekosystemu można uznać za dojrzałe. Mieliśmy ochotę na odrobinę przygody, więc zrezygnowaliśmy ze zwykłych interfejsów API JSON i od razu się w nie zagłębiliśmy - oto, czego się dowiedzieliśmy.
Potrzebny jest serwer GraphQL
W większości frameworków używanych do tworzenie stron internetowychNarzędzia do tworzenia JSON API już istnieją. Możesz zbudować strukturę trasy i łatwo zaakceptować niektóre GET i POST, a następnie wyprowadzić odpowiedź JSON. Ruby on Rails ma nawet specjalną funkcję projekt przełącznik konfiguracji, który rezygnuje ze zwykłych dodatków do renderowania HTML i stawia solidną podstawę dla interfejsów API. Wynika z tego, że wykwalifikowany programista korzystający z nowoczesnych narzędzi może przygotować backend w dosłownie kilka minut.
Inaczej jest w przypadku GraphQL. Chociaż istnieją biblioteki serwerowe dla wiele językówWciąż jednak ponosisz karę za szybkość zaraz po wyjściu z bramki - po prostu musisz dowiedzieć się, co jest odpowiednie dla twojego ekosystemu. Osobiście nie przepadam też za terminem "serwer" używanym do opisania biblioteki, którą można wprowadzić do projektu.
Jest tylko jeden punkt końcowy
Przez lata przyzwyczailiśmy się do określonego sposobu myślenia o strukturze API. Na najbardziej podstawowym poziomie po prostu stosowaliśmy praktyki REST. Oznaczało to utworzenie kilku punktów końcowych dla każdego modelu logicznego w naszej aplikacji. Jest to struktura łatwa do zrozumienia zarówno dla autorów API, jak i konsumentów. Tworzy również dobrze podzielone metody w backendzie, dzięki czemu wnioskowanie o kod tak łatwo, jak o samym API. Struktura ta jest również łatwa do umieszczenia w przestrzeni nazw, np. dla celów Wersjonowanie API.
GraphQL wykorzystuje tylko jeden punkt końcowy, zwykle /graphql
. Każde żądanie do twojego API dotrze jako żądanie POST do tego punktu końcowego, a stamtąd obowiązkiem serwera GraphQL jest dowiedzieć się, czego chce klient i odpowiednio odpowiedzieć.
Na pierwszy rzut oka wydaje się to nieporęczne: wyobraź sobie, że próbujesz zrobić wszystko w JSON API za pomocą jednego punktu końcowego! Jednak wkrótce zaczyna to mieć sens, gdy interfejs API dojrzewa i niektóre rzeczy są zastępowane innymi. Deprecjacja w klasycznych API odbywa się zwykle na poziomie przestrzeni nazw, przechodząc od v1
do v2
. GraphQL zapewnia znacznie większą kontrolę, aż do wycofania pojedynczego pola. Wyobraź sobie, że jesteś w stanie powiedzieć konsumentowi REST API, że nie chcesz, aby używał pola nazwa
i używać fancy_name
zamiast tego! Okazuje się, że to, co początkowo wydawało się nieporęczne, jest w rzeczywistości jedną z najlepszych funkcji.
Wszystko jest wpisywane
JSON tak naprawdę nie ma zbyt wielu możliwości wpisywania. Dostępne są ciągi znaków, liczby, tablice i obiekty. Poza tym nie masz szczęścia. W przeciwieństwie do tego, w GraphQL wszystko zaczyna się i kończy na typach, ponieważ nawet root Query i Mutation są właśnie tym - typami. GraphQL DSL wymusza sprawdzanie typów zarówno na serwerze, jak i kliencie, zapobiegając wszelkiego rodzaju nieprzyjemnym niespodziankom.
Jest to bardzo ważne, zwłaszcza że SPA coraz częściej same sprawdzają typ, czy to za pomocą TypeScript, czy alternatyw, takich jak Flow. GraphQL ułatwia wprowadzanie złożonych i złożonych typów oprócz wartości domyślnych i szybko staje się drugą naturą dla programistów zarówno na zapleczu, jak i na frontendzie.
Czytaj więcej: Testowanie JavaScript... z Ruby?!
Dokumenty są wbudowane
W klasycznym interfejsie API JSON dokumentacja może być kwestią drugorzędną. A nawet jeśli tak nie jest, istnieje wiele metod do wyboru. Czy używamy jakiegoś schematu, takiego jak OpenAPI? Czy następnie konwertujemy je do postaci czytelnej dla człowieka za pomocą narzędzi takich jak Swagger? A może po prostu wrzucamy gdzieś całą masę plików Markdown? Nawet jeśli ten problem był już wielokrotnie rozwiązywany, nadal wymaga świadomego myślenia i wysiłku ze strony zespołu - najpierw w celu stworzenia dokumentacji, a następnie jej aktualizacji i rozpowszechniania. Jest to jeszcze bardziej złożony problem, gdy API ma kilka sekcji, które są dostępne tylko dla np. określonych ról użytkowników.
W GraphQL dokumentacja jest pierwszorzędnym obywatelem, ponieważ większość serwerów umożliwia dokumentowanie typów i żądań na miejscu. Od początku 2018 roku GraphQL Schema Definition Language stał się częścią oficjalnej specyfikacji, więc istnieje dokładnie jeden sposób dokumentowania GraphQL API. Ponadto, ponieważ GraphQL umożliwia definiowanie widoczności niektórych części wykresu, użytkownicy, którzy nie powinni, automatycznie nie widzą dokumentów dotyczących tego, do czego nie mają dostępu. Podjęcie decyzji i jasne wytyczne były wielkim dobrodziejstwem dla zespołu.
Istnieją tylko dwa rodzaje działań
W przeciwieństwie do HTTP GET, POST, PUT, PATCH i DELETE, w GraphQL istnieją tylko dwa rodzaje akcji: Zapytania i Mutacje. Główna różnica polega na tym, że mutacje mogą i będą zmieniać stan systemu, a zapytania będą tylko pasywnie odczytywać dane.
Przyznam, że wciąż jestem niezdecydowany w tej kwestii. Podoba mi się mnogość czasowników HTTP do interakcji z zasobami i możliwość użycia dokładnie odpowiedniego narzędzia do pracy. GraphQL ułatwia dbanie o te włochate przypadki, w których którykolwiek z czasowników HTTP nie pasował dokładnie, ale ponosi karę za konieczność zastanowienia się, na co konkretna mutacja faktycznie wpłynie. Można również zauważyć, że ponieważ tak naprawdę nie ma wbudowanej standardowej konwencji nazewnictwa, będziesz musiał sporządzić wewnętrzne przewodniki stylu lub ryzykować zbudowanie niespójnego bałaganu.
W zasadzie potrzebujesz klienta
Interakcja z interfejsami API REST przez HTTP jest bardzo łatwa w waniliowym JavaScript, a jeszcze łatwiejsza przy użyciu nowoczesnego pobieranie
API. Z kolei w przypadku GraphQL należy użyć biblioteki klienckiej, jeśli chce się uzyskać naprawdę przyzwoitą wydajność. Interakcja z interfejsem API GraphQL przy użyciu tylko waniliowego JavaScript nie jest niemożliwa - w końcu to tylko żądania POST. Jednak korzystanie z długotrwałych technologii internetowych, takich jak buforowanie żądań dla typowych wywołań API, nie będzie działać, ponieważ żądania POST zazwyczaj nie są buforowane.
Każdy rozsądny klient GraphQL implementuje mechanizm buforowania wyników po stronie klienta i wiele innych funkcji. Dzięki tym wszystkim wyborom ręczne tworzenie konfiguracji dla klienta GraphQL na poziomie podstawowym jest zadaniem całkowicie ogłupiającym. Podczas rozpoczynania pracy z GraphQL szczególnie polecam przyjrzeć się Apollo-Boost ponieważ ma bardzo rozsądne ustawienia domyślne.
Klient wybiera dane
Wszyscy byliśmy w takiej sytuacji: wyciągamy listę danych z API i brakuje w niej jakiegoś kluczowego pola dotyczącego powiązanego modelu. Następnie wdrażamy hack obejmujący N+1 żądań, jednocześnie narzekając na programistów backendu, którzy szybko je dodają. Zwykle nie ma to miejsca w przypadku dobrze zaimplementowanego interfejsu API GraphQL, ponieważ możemy po prostu zagłębić się w dane tak głęboko, jak nam się podoba. Chcesz zobaczyć adres klienta w zamówieniu w tej partii? Żaden problem - przynajmniej w teorii, co prowadzi nas do...
Złożoność jest trudniejsza do przewidzenia
Podczas projektowania GraphQL od strony zaplecza może być trudno myśleć o całej głębi, jaką klient może zagłębić w wykres. Istnieje wiele sposobów na oprzyrządowanie i obserwowanie wykorzystania wykresu, a po pozwoleniu kolegom z front-endu na chwilę zabawy możesz zacząć widzieć długie zapytania wykonujące dość wymyślne odczyty w magazynie danych. W REST API jest to łatwiejsze do kontrolowania, ponieważ można łatwo określić zakres danych, które będą dostępne w pojedynczym żądaniu. Często ta pominięta złożoność może mocno ugryźć po wydaniu na produkcję. W wielu przypadkach nie jest też oczywiste, jak wydostać się z tej dziury, którą sam sobie wykopałeś.
Numerowane strony są naprawdę trudne
Jest to zarzut, który jest naprawdę z przymrużeniem oka. Zdecydowanie można poczuć, że GraphQL został zaprojektowany na Facebooku i dla Facebooka, patrząc na sposób, w jaki działa zamierzony mechanizm paginacji. Tak zwane Connections to w zasadzie niekończące się strumienie krawędzi grafu, po których nawigacja odbywa się za pomocą kursorów zamiast bardziej klasycznych stron. Chociaż łatwo jest zobaczyć, jak pasuje to do niekończącego się kanału postów w stylu Facebooka, jeśli chcesz mieć starannie podzieloną na strony listę z możliwością przejścia do, powiedzmy, strony 42, będziesz miał znacznie trudniejszy czas. Istnieją oczywiście sposoby na obejście tego problemu, ale tym właśnie są - obejściami.
Czy zrobilibyśmy to ponownie?
Biorąc pod uwagę wszystkie wymienione powyżej zastrzeżenia i różnice, prawdopodobnie myślisz, że traktujemy GraphQL jako eksperyment, który okazał się kwaśny i powrócił prosto do interfejsów API REST. To nieprawda. Jeśli już, to pracujemy nad szerszym wykorzystaniem GraphQL w projektach w całej organizacji. To świetna technologia, która sprawiła, że nasza praca stała się łatwiejsza i lepsza. Początkowo zainwestowaliśmy jednak w GraphQL, nie zdając sobie do końca sprawy z tego, przez jakie bóle wzrostowe będziemy przechodzić.
Jeśli uważasz, że GraphQL może być dla Ciebie odpowiedni, zachęcam do podjęcia decyzji. Daj sobie wystarczająco dużo czasu i miejsca na bezpieczne porażki, a wkrótce zaczniesz czerpać korzyści!
Czytaj także:
– Jak skutecznie zarządzać zdalnymi programistami? Przewodnik dla CTO
– Python vs. Ruby? Której technologii należy użyć do rozwoju produktu?
– Krótki przewodnik po budowaniu i rozwijaniu własnego rynku. Co warto wiedzieć?