w Praktyce
3 godz. 17 min · ReactJS · Full-stack i Programowanie
Przemysław NowakSoftware EngineerJeżeli masz już doświadczenie w tworzeniu aplikacji komunikujących się z backendem to z pewnością wiesz czym jest ból niespójnego API oraz wielu sposobów wykonywania requestu po dane. Apollo rozwiązuje ten problem udostępniając jedno proste API do obsługi komunikacji z serwerem GraphQL. Nie musisz się martwić o to jak otworzyć kanał WebSocket dla subskrypcji czy o to jak napisać poprawny Query Document - to wszystko i jeszcze więcej dostarcza dla nas Apollo Client.
Apollo 3 posiada niesamowity mechanizm cache, który pozwala zaoszczędzić czas na wykonywanie zapytań oraz setup bibliotek do przechowywania stanu serwera. Wszystkie request trafiają do warstwy pamięci podręcznej, którą zarządza dla nas Apollo - wybiera, dodaje oraz łączy odpowiednie podzbiory tak aby jak najmniej komunikować się z serwerem, a mimo to wiedzieć jaki jest jego stan. Dodatkową cechą mechanizmu Cache jest to, że może być łatwo użyty jako stan lokalny - bez potrzeby instalowania bibliotek takich jak Redux, jesteśmy w stanie stworzyć aplikację stateful w niesamowitym tempie!
Być może spotkałeś się już kiedyś z problemem Unit Testów, które działają - są na "zielono" ale mimo wszystko aplikacji jest zepsuta - to przykład źle napisanych jednostek. Komunikacja z serwerem i odbieranie danych to kluczowy element każdej aplikacji - dlatego ważne jest aby stworzyć poprawne unit testy, które będą nas chronić przed zepsutą aplikacją na produkcji. W kursie tym poznasz poprawny sposób na testowanie klienta Apollo, tak aby testy były stabilne i spełniały swoją rolę.
Z pewnością wyobrażasz sobie magiczne aplikację, które działają szybko bez potrzeby czekania na odpowiedzi z serwera oraz posiadające poprawne dane. Skoro tak, wiesz również, że stworzenie takich aplikacji wymaga wiele pracy, dodatkowych bibliotek oraz rozpisania każdego przypadku, tak aby wiedzieć kiedy dane są poprawne a kiedy trzeba zapytać serwer o nie jeszcze raz... A co jeżeli Ci powiem, że Apollo zrobi to za nas? Podejście Cache-First, o które oparta jest biblioteka klienta apollo dostarcza nam te wszystkie w/w cechy, a kurs ten pokaże Ci jak sprawnie posługiwać się tymi narzędziami.
Apollo to poważny gracz w wielu stackach technologicznych. Jeżeli firma decyduje się używać GraphQL - który jest coraz bardziej popularny - to przeważnie w parze idzie Apollo. Dlatego w wielu ofertach pracy możesz spotkać tą technologię jako wymaganą. Zresztą, nie bez przyczyny, Apollo pozwala na sprawne, spójne oraz szybkie budowanie aplikacji czy to z Reactem, czy to z Angularem, Vue, Svelte oraz z Androidem czy iOS - mając jeden wspólny interfejs pracy, firmy są wstanie tworzyć aplikację w różnych technologiach komunikujących się z warstwą Apollo w jeden określony sposób.
Kurs ten jest stworzony z myślą o FrontEnd developerach znających ReactJS oraz podstawy GraphQL, którzy chcą dodać do swojego arsenału technologicznego poważną broń jaką jest Apollo.
Zanim jeszcze przejdziemy do narracji, chciałbym Ci w tej krótkiej lekcji
pokazać na takich prostych przykładach jak ten lekarz tak naprawdę działa.
Też. Tak jak wspomniałem jest to warstwa
do sterowania danych czy raczej query w pamięci podręcznej.
I tutaj jest dokładnie taki sam opis
i to co nam umożliwia to ten kesz to to, że przyszły query z tymi samymi danymi
nie potrzebują wysyłać requestów, ponieważ dostaną je z kesza.
I ta warstwa działa bardzo fajnie.
Natomiast tak jak widziałeś na pierwszej
lekcji, my sobie ten Apollo client skonfigurować.
Byliśmy w taki sposób, że mamy tutaj domyślne opcje
I to działa, ponieważ kiedy zerkniemy sobie na naszą aplikację i zerkniemy na
cash, to mamy tutaj root query i w tym query mamy zapisane nasze dane.
Więc następnym razem, kiedy wykonamy dokładnie takie samo Query WR
na Product Imagination i zapytamy itemy i dokładnie o takie same elementy w tych
rytmach, to również to zadziała i dane zostaną zwrócone.
Natomiast wróćmy jeszcze do dokumentacji
i chciałbym, żebyśmy tutaj przeszli przez kilka rzeczy i przede wszystkim tutaj mamy
pewne opcje konfiguracyjne, abyśmy mogli sobie te cash dostosować.
Możemy tutaj stworzyć jakieś własne
primary key i powiem Ci za chwilkę czym to jest.
Możemy tutaj również stworzyć swoją
interpretację dla podstawy dla pól, czyli to co będziemy
zwracać na przykład możesz sobie wyobrazić i za chwilę również Ci to pokażę, że
zawsze dla pola niech będzie kategorii chcielibyśmy zwrócić to pole.
Z czasem również mamy zdefiniowany kernel
i tym się zajmiemy w następnej lekcji oraz dodatkowo możemy zarządzać takim
lokalnym stanem, gdybyśmy chcieli również tworzyć lokalny stan tylko z Apollo.
I tak robimy w tej naszej aplikacji,
to możemy również tutaj tym stanem zarządzać, modyfikować go itd.
Czyli nie potrzebowalibyśmy np.
redaktora czy kontekstu czy innych tego typu rzeczy.
Przechodząc niżej możemy zobaczyć tutaj informację o normalizacji danych.
Tutaj jedną ważną rzeczą jest to, że te
dane kiedy przychodzą nowe dane będą te dane.
MERGE Czyli tutaj jest ta informacja, czyli to jest to, o czym mówiliśmy.
Mówiłem, że te dane będą się merge między
sobą, kiedy te nowe, kolejne będą przychodzić.
Na ten przykład możesz sobie wyobrazić, że
na początku w pierwszym query robiliśmy tylko dwa pola,
w trzecim dodaliśmy kolejne, więc ten obiekt w katalogu zostanie z merge.
To trzecie pole do tego obiektu zostanie dodane.
Za chwilę Ci to pokażę, jak by to mogło na przykładzie wyglądać.
Ale jest tutaj jeszcze jedna ważna rzecz.
Jest to informacja o generowaniu unikatowych identyfikatorów.
Generalnie jeżeli chodzi o całe
identyfikatory to Apollo nigdy nie tworzy folderów.
Czyli jest tutaj ta informacja o Apollo 2.
Tak było i czasami upgrade do Apollo czy powodował właśnie takie bugi?
Ponieważ Apollo 3 nigdy nie tworzy braków
jeżeli nie ma jakiegoś identyfikatora dla danego pola.
Tego po prostu nie tworzy.
Zawsze takie pole musi mieć ID i to ID.
Poprzez tę ideę możemy mieć osobny klucz.
Jeżeli popatrzymy na nasze dane to dokładnie tak tutaj to wygląda.
My mamy po prostu Ród Query
i to jest jedno pole, dlatego, że nie mamy tutaj nigdzie pola ID.
To dostaliśmy wszystko tutaj zrzucone do
tego jednego pola root query w i where i mamy tutaj całą tą informację.
Natomiast możesz sobie wyobrazić, że gdybyśmy tutaj mieli pole ID,
gdzie rzeczywiście takim naszym ID mógłby być protected,
to wówczas tutaj dostalibyśmy osobne klucze dla każdego z tych produktów.
To jest oczywiście bardzo ważne, ponieważ
jeżeli tutaj dodamy ID zostanie to zapisane w takiej formie np.
mamy task dwukropek 14, przy czym ten dwukropek to jest ten kropek, right?
I dokładnie tak jak mówisz.
Dlaczego to jest ważne?
Wyobraź sobie, że teraz będziemy przechodzić na szczegóły tej strony.
W momencie kiedy przechodzimy na szczegóły
tej strony, to może również byśmy mogli mieć te dane od razu bez potrzeby
wykonywania query i wtedy moglibyśmy mieć te dane właśnie z
kesza, ponieważ jak sobie wyobrazić takie klarowanie?
Tutaj byłoby po szczegóły, natomiast samo query byłoby raczej podobne.
Mielibyśmy tutaj kilka dodatkowych pól, ale tak naprawdę moglibyśmy dostać od razu
te dane z kesza, ponieważ byśmy mieli zdefiniowane protected.
Nie dostalibyśmy ich w tym przypadku,
ponieważ nasze query mówi, że chcemy produkt Nation, a na tej stronie nie
będziemy kierować produktami Nation, tylko Product Details.
Więc jeżeli będziemy mieć inne query, ale byśmy dostali te same pola dla tego typu.
To wtedy od razu byśmy je tutaj dostali.
I to, że coś działa możesz zauważyć właśnie w tym miejscu.
Aktualnie nie mamy tutaj żadnych query.
Jest kesz, mamy uzupełniony.
Ale jeżeli zerkniemy na network i popatrzymy teraz, w momencie, gdy
przechodzimy na All products, możesz zauważyć, że nic się nie stało.
Nie dostaliśmy żadnego query i te dane zostały od razu zwrócone z kesza.
A więc to jest właśnie ta magia Apollo, że nie mamy niepotrzebnych zapytań, że to
wszystko działa bardzo szybko i dynamicznie.
Gdybyśmy mieli predefiniowane te dane w
postaci tak jak mówiłem, możesz sobie wyobrazić właśnie produkty RAID, prawda?
No to wtedy od razu, również przechodząc
tutaj, dostalibyśmy te dane z kesza, oczywiście przy odpowiednim query.
Natomiast kiedy byśmy otwierali stronę,
to wtedy już byłby pusty, więc automatycznie dostalibyśmy request.
I oczywiście to jak to działa poznasz w
kolejnej lekcji, kiedy będziemy implementować tą stronę szczegółów.
Natomiast chciałbym troszeczkę teorii
tutaj wszczepić, żebyś widział jak to działa.
I teraz chciałbym Ci pokazać na praktyce
jak możemy takie Product ID uzyskać i osobne klucze w tym celu.
Jak na razie mamy jeden obiekt, a my byśmy chcieli mieć kilka.
I na to są dwa sposoby.
Jednym sposobem jest to, abyśmy w pliku
pliku index czyli product page tu gdzie mamy to query
zapisali jako protected po prostu id, czyli stworzyli tutaj alias
powinien być dla Ciebie znajomy jeżeli oglądałeś poprzednie kursy,
więc zapiszmy to i teraz zobaczmy jak to będzie wyglądało.
Oczywiście odśwież stronę i zobaczmy na całość
i zobacz, że teraz mamy właśnie tą składnie product dwukropek id.
Ponieważ Apollo dostało informację co tym
identyfikatorem jest, więc zapisał osobne klucze.
I teraz kiedy byśmy przechodzili np.
na ten produkt id 5 tutaj jest to undefined.
Ponieważ teraz w template mamy tutaj
problem, czyli w tym miejscu wyświetlamy ciągle ID.
Musielibyśmy to zmienić na a wyświetlamy protected.
Natomiast na tym się nie skupiajmy.
W momencie kiedy przechodzi na to,
to od razu kesza moglibyśmy dostać te dane, więc nie byłoby potrzeby wykonywania
query, więc działałoby to bardzo szybko i
dynamicznie, więc bardzo również fajnie z poziomu użytkownika
OK i jest jeszcze jeden sposób jak to możemy zrobić.
Natomiast jeżeli zerkniemy na to root query to mamy tutaj jeszcze jedną rzecz,
czyli jeżeli pójdziemy do items to mamy teraz tutaj Ref.
A i my mamy tutaj informację, że.
Tutaj już nie trzymamy tych danych, ale trzymamy referencje.
Czyli ja mówię, że moim i na indeksie
trzecim jest referencja do produktu ID, a więc poszukaj sobie tego protected.
I teraz jak tu przejdziemy to mamy
wszystkie te dane, ale my również mamy tutaj kategorie.
Ja bym chciał, żeby ta
kategoria również siedziała sobie w innym miejscu, czyli nie była tutaj zastosowana,
tylko tutaj również chciałbym mieć referencje i chciałbym mieć osobny klucz,
bo być może kiedyś będę chciał pobrać tylko informacje o kategorii.
Chciałbym ją mieć od razu w jednym osobnym kluczu, gdzie to zawsze będziemy.
Więc zobaczmy sobie tutaj i moglibyśmy to zrobić.
Mamy tutaj takie pole jak Category id
i również możemy zrobić to sam, czyli stworzyć alias kategorii id jako ID.
I zobaczmy jak to wygląda.
Jak wiesz my.
I przejdźmy do Łukasza i zobacz, że mamy
tutaj również już teraz osobne klucze dla każdego ID i mamy tu te informacje.
Więc gdybyśmy teraz robili query a taką
kategorię, to już dostaliśmy ją również z kesza.
A nie będziemy potrzebować mieć jakby osobnego requestów.
Ale co się stało? Oczywiście w produkcie
to również mamy tutaj referencję, a więc dla tego produktu ID 4 kategoria to jest
referencja do kategorii 2, a kategorii 2 jest tutaj uzupełniony tymi danymi.
A więc tak się buduje cały katalog i w taki sposób możesz budować.
Kiedy wiesz, że wykonujesz coś na route query i nie ma to pól ID,
to wtedy warto właśnie sobie tak zdefiniować te ID.
Albo za pomocą aliasów, albo.
I tutaj jest właśnie kolejna kwestia jak możemy to zrobić?
Gdybyśmy nie chcieli mieć tych aliasów, a
utrzymywać jednak takie pole, to możemy również przejść do dokumentacji.
I jest tutaj taka informacja,
że możemy definiować GPS i field są bardzo przydatne w momencie
kiedy nie mamy takiego ID i wtedy byśmy chcieli w jakiś sposób
również mieć zapisany dany element w osobnym kluczu.
Ale nie mamy ID, więc nie mamy jak go zidentyfikować, więc chcielibyśmy w jakiś
sposób stworzyć własne customowe identyfikator
i to jak możemy to zrobić to możemy sobie teraz już przejść do klienta.
I tutaj możemy zdefiniować zdefiniować
opcje i te opcje jakie się tutaj definiują to są właśnie polityki pull.
A więc tak ja bym tutaj chciał zrobić typu less dla
naszego produktu, ponieważ ten nasz produkt to jest nasz
właśnie ten site, również kategorii, to jest nasza kategoria.
Jeżeli jeszcze raz byś sobie tutaj
podglądał to w Traffic Wheel w dokumentacji
to dokładnie zobaczysz, że kategoria jest to typ kategorii.
I jeżeli zerkniemy na product
to product jest to typ product, czyli właśnie do tego typu product się będziemy
odwoływać i do tego typu kategorii będziemy się również odwoływać w.
A więc robimy to w taki sposób.
I teraz bym chciał zdefiniować sobie jaki
filtr i moim filtrem dla produktu będzie Product ID.
Czyli ja mówię, że ten produkt to jest mój kluczowy.
To jest moje kluczowe pole, na podstawie
którego zbuduj wartość identyfikator kesza i na podstawie
tego identyfikatora będziesz wybierał ten produkt w naszych query.
Tak więc przejdźmy sobie tutaj.
Zobaczmy jak to wygląda.
Odśwież stronę.
I jest tutaj pewna różnica.
Możesz zobaczyć, że jest to jakby obiekt.
Czyli mamy tutaj taki serializacji na obiekt protected.
Natomiast jeżeli jesteś pewny Ty jako
twórca oprogramowania, to wiesz, że ten produkt będzie zawsze unikatowy, więc nie
ma znaczenia, że to jest realizowany obiekt, bo wiesz, że tutaj np.
zawsze ten product IT jest unikatowy, więc nigdy nie będzie takiej sytuacji, że
będziesz miał dwa razy produkty ID 8 i wtedy mógłbyś mieć jakieś bugi.
Więc jeżeli byś teraz zamienił to i użył tutaj produkt field jako name
to to będzie troszeczkę problematyczne, ponieważ możesz mieć takie samo name
i wtedy gdybyś dostał takie samo name produktu no to
może to powodować bugi, ponieważ czasami możesz dostać ten produkt, a czasami ten
i to będzie powodowało z pewnością jakieś błędy.
A więc musisz być bardzo ostrożny i musieć.
Musisz wiedzieć, że tymi filtrami powinny być właśnie unikatowe wartości.
Natomiast ja bym chciał jeszcze dodać taki filtr dla kategorii.
Więc możemy to tak samo zrobić.
Czyli zapiszmy sobie tutaj kategorii i dla kategorii.
Moim filcem
będzie również kategoria ID, ale również chciałbym, żeby było to
również name, a więc jestem pewny, że kategoria
unikatowe, ale być może nam również będzie unikatowy.
Więc chciałbym złączyć to sobie i
zrealizowany mieć taki obiekt z tych dwóch pól.
I wtedy, kiedy zerkniemy sobie tutaj,
odśwież stronę i zobaczmy jakież
to właśnie możemy zobaczyć, że tak wygląda nasz serwis serializacji na obiekt.
I taki obiekt powinien być zawsze unikatowy.
Więc w przypadku, kiedy nie masz jednego pola unikatowego na przykład a wiesz, że
połączenie dwóch pól zawsze da unikatowy rezultat, to również w taki sposób możesz
stworzyć identyfikator w tym akurat miejscu.
Nie ma to sensu, ponieważ kategoria ID
zawsze będzie unikatowy, natomiast połączenie jakiegoś innego pola tutaj
gdyby było unikatowe z połączeniem pola name to również to zadziała.
Ja jeszcze bym chciał zrobić jedną rzecz, czyli pokazać Ci, że
tak naprawdę możemy jeszcze tego aplikacja zrobić na jakimś konkretnym polu, więc
możemy tutaj również zdefiniować sobie pole.
I jeżeli definiujemy definiujemy pole field, to w polu fields powinniśmy
definiować pola dla tego konkretnego, dla tego konkretnego typu.
I np.
takim polem jest name, ponieważ kategoria ma name i również takimi polami np.
dla produktu byłoby unit price name.
A więc każde pole, które występuje
na naszym typie możemy tutaj coś z nim zrobić.
I to name jest tak naprawdę funkcją.
I tutaj jako pierwszy argument otrzymujemy
tę wartość z kesza, czyli to jest to skasowany pole name.
Ja bym chciał, żebyśmy zwrócili tutaj zamiast tego zwykłego name, ponieważ
domyślnie ta funkcja działa właśnie w taki sposób.
Ja bym chciał, żebyśmy tutaj zrobili tu
upper case i teraz kiedy to zapiszemy, wrócimy na stronę i odświeżamy stronę.
To jak widzisz nasze kategorie są już powiększone, są zrobione jako APR case,
więc to wszystko działa i w taki sposób również możemy sobie modyfikować kesza.
Możemy również tutaj wpisywać inne
wartości z kesza możemy mordować rzeczy, możemy dodawać coś do kesza itd.
Itd. Więc moglibyśmy tutaj powiedzieć name + 2.
I również to oczywiście zadziała.
Więc tak, właśnie w taki sposób możemy tworzyć jakieś
unikatowe rzeczy czy customowe rzeczy jeżeli chodzi o ten stan kesza.
No i myślę, że to tyle tytułem wstępu.
Więc przejdźmy już do kolejnej lekcji, gdzie za implementujemy sobie nacje.