Vi skriver 2020. Dit team hælder i stigende grad til at bygge enkeltside-applikationer eller i det mindste inkludere rige komponenter i almindelige flersidede applikationer. [GraphQL](https://graphql.org/) er [over to år gammel](https://en.wikipedia.org/wiki/GraphQL) nu, hvilket efter JavaScript-økosystemets standarder kan betragtes som modent. Vi følte os lidt eventyrlystne, så vi droppede de sædvanlige JSON-API'er og kastede os ud i det - her er, hvad vi lærte.
Det er 2020. Din hold hælder i stigende grad til at bygge enkeltside-applikationer eller i det mindste inkludere rige komponenter i almindelige flersidede applikationer. [GraphQL](https://graphql.org/) er [over to år gammel](https://en.wikipedia.org/wiki/GraphQL) nu, hvilket med JavaScript økosystemstandarder kunne betragtes som modne. Vi følte os lidt eventyrlystne, så vi droppede de sædvanlige JSON-API'er og kastede os ud i det - her er, hvad vi lærte.
Du har brug for en GraphQL-server
I de fleste frameworks, der bruges til webudviklingVærktøjerne til at opbygge en JSON-API er der allerede. Du kan opbygge en rutestruktur og nemt acceptere nogle GET's og POST's og derefter udsende et JSON-svar. Ruby on Rails har endda en særlig projekt setup-switch, der fjerner de sædvanlige HTML-rendering-godbidder og sætter et solidt grundlag for API'er i stedet. Det betyder, at en dygtig udvikler, der bruger moderne værktøjer, kan lave en backend på bogstaveligt talt få minutter.
Sådan er det ikke med GraphQL. Mens der findes serverbiblioteker til mange sprogMen hvis man ikke gør det, bliver man stadig straffet på hastigheden lige fra starten - simpelthen fordi man skal finde ud af, hvad der passer til ens økosystem. På et mere personligt plan er jeg heller ikke glad for, at udtrykket "server" bruges til at beskrive et bibliotek, der kan introduceres i et projekt.
Der er kun ét slutpunkt
I årenes løb har vi vænnet os til en bestemt måde at tænke på, når det gælder API-struktur. På det mest grundlæggende niveau fulgte vi simpelthen REST-praksis. Det betød, at vi oprettede flere endpoints pr. logisk model i vores app. Det er en struktur, der er let at forstå for både API-forfattere og -brugere. Det giver også velafgrænsede metoder i backend, hvilket gør det lettere at ræsonnere om Kode lige så let som om selve API'et. Denne struktur er også nem at navngive, f.eks. i forbindelse med API-versionering.
GraphQL anvender kun et enkelt slutpunkt, ofte /graphql
. Hver anmodning til din API ankommer som en POST-anmodning til dette slutpunkt, og derfra er det GraphQL-serverens ansvar at finde ud af, hvad klienten ønsker, og svare på passende vis.
Ved første øjekast føles det uoverskueligt: Forestil dig, at du prøver at gøre alt i en JSON API med et enkelt endpoint! Det begynder dog hurtigt at give mening, når dit API modnes, og nogle ting erstattes af andre. Deprecation i klassiske API'er sker normalt på namespace-niveau, hvor man flytter fra v1
til v2
. GraphQL giver meget mere kontrol, helt op til at afskaffe et enkelt felt. Forestil dig at kunne fortælle en REST API-forbruger, at du ikke vil have, at de bruger Navn
feltet og at bruge fancy_name
i stedet! Det viser sig, at det, der først føltes uhåndterligt, faktisk er en af de bedste funktioner.
Alt er indtastet
JSON har egentlig ikke så mange typemuligheder. Der er strenge, tal, arrays og objekter. Ud over det har du ikke heldet med dig. I GraphQL derimod begynder og slutter alt med typer, da selv roden Query og Mutation er netop det - typer. GraphQL DSL håndhæver typekontrol på både serveren og klienten, hvilket forhindrer alle mulige ubehagelige overraskelser.
Det er meget vigtigt, især fordi SPA'er i stigende grad selv bliver typetjekket, hvad enten det er ved hjælp af TypeScript eller alternativer som Flow. GraphQL gør det nemt at introducere komplekse og sammensatte typer oven på standardværdierne, og det bliver hurtigt en selvfølge for udviklere i både backend og frontend.
Læs mere om det: Test af JavaScript ... med Ruby!
Dokumenterne er indbygget
I et klassisk JSON-API kan dokumentationen være en eftertanke. Og selv hvis den ikke er det, er der mange metoder at vælge imellem. Skal vi bruge et skema som OpenAPI? Konverterer vi det så til menneskeligt læsbar form med værktøjer som Swagger? Eller dumper vi bare en masse Markdown-filer et eller andet sted? Selv om dette problem er blevet løst flere gange, kræver det stadig bevidst tankevirksomhed og indsats fra teamet - først for at opbygge dokumenterne og derefter for at holde dem opdateret og udbredt. Det er et endnu mere komplekst problem, når API'en har flere sektioner, som kun er tilgængelige for f.eks. bestemte brugerroller.
I GraphQL er dokumentation en førsteklasses borger, da de fleste servere giver mulighed for at dokumentere dine typer og anmodninger på stedet. Siden begyndelsen af 2018 har GraphQL Schema Definition Language været en del af den officielle specifikation, så der er præcis én måde at dokumentere en GraphQL API på. Og da GraphQL gør det muligt at definere synligheden af visse dele af grafen, forhindres de brugere, der ikke skal have adgang, automatisk i at se dokumenter for det, de ikke har adgang til. Det har været en stor fordel for teamet, at beslutningen er taget, og at der er klare retningslinjer.
Der er kun to typer af handlinger
I modsætning til HTTP's GET, POST, PUT, PATCH og DELETE er der kun to typer handlinger i GraphQL: Forespørgsler og mutationer. Hovedforskellen er, at mutationer kan og vil ændre systemets tilstand, mens forespørgsler kun passivt vil læse data ud.
Jeg må indrømme, at jeg stadig er i tvivl om dette. Jeg nyder HTTP's overflod af verber til at interagere med ressourcer og være i stand til at bruge det helt rigtige værktøj til jobbet. GraphQL gør det nemmere at tage sig af de hårrejsende tilfælde, hvor et af HTTP-verberne ikke passede nøjagtigt, men straffen er at skulle tænke over, hvad en bestemt mutation faktisk vil påvirke. Man kan også sige, at eftersom der ikke er nogen indbygget standardnavngivningskonvention, er man nødt til at udarbejde interne stilguider eller risikere at opbygge et inkonsekvent rod.
Du har stort set brug for en klient
At interagere med REST API'er over HTTP er super nemt i vanilla JavaScript, og endnu nemmere med den moderne Hent
API. Til GraphQL skal du derimod bruge et klientbibliotek, hvis du vil have en virkelig god performance. Det er ikke umuligt at interagere med en GraphQL API ved hjælp af vanilje JavaScript - det er trods alt bare POST-anmodninger. Men at bruge gamle webteknologier som caching af anmodninger til almindelige API-opkald vil ikke fungere, da POST-anmodninger generelt ikke cachelagres.
Enhver fornuftig GraphQL-klient implementerer en caching-mekanisme for resultater på klientsiden og mange flere funktioner. Takket være alle disse valgmuligheder er det en helt uoverskuelig opgave at lave en konfiguration til en GraphQL-klient på begynderniveau. Når du starter med GraphQL, anbefaler jeg især, at du tager et kig på Apollo-Boost da den kommer med meget rimelige standardindstillinger.
Klienten vælger data
Vi har alle været der: Vi trækker en liste med data ud fra API'en, og den mangler et afgørende felt om en relateret model. Derefter implementerer vi et hack, der involverer N+1 anmodninger, mens vi brokker os over backend-udviklerne, der skynder sig at tilføje det. Det er normalt ikke tilfældet med en velimplementeret GraphQL API, da vi bare kan dykke så dybt ned i dataene, som vi har lyst til. Har du brug for at se adressen på en kunde på en ordre i denne batch? Ikke noget problem - i hvert fald i teorien, hvilket fører os videre til...
Kompleksitet er sværere at forudse
Når man designer GraphQL fra backend-siden, kan det være svært at tænke på alle de dybder, en klient kan dykke ned i grafen. Der er mange måder at instrumentere og observere brugen af din graf på, og når du har ladet dine frontend-kolleger lege lidt, kan du begynde at se nogle lange forespørgsler, der udfører ret fantasifulde læsninger af dit datalager. I en REST API er det nemmere at kontrollere, da du nemt kan fortælle, hvor mange data der skal tilgås i en enkelt forespørgsel. Ofte kan denne ubesvarede kompleksitet bide dig hårdt, når du frigiver til produktion. Mange af disse gange er det heller ikke indlysende, hvordan man undslipper det hul, man har gravet for sig selv.
Nummererede sider er virkelig svære
Dette er en kritik, der egentlig er ironisk. Man kan helt klart mærke, at GraphQL er designet på og til Facebook, når man ser på, hvordan den tiltænkte pagineringsmekanisme fungerer. De såkaldte Connections er dybest set endeløse strømme af grafkanter, som man navigerer i via cursorer i stedet for de mere klassiske sider. Det er nemt at se, hvordan det passer til et endeløst feed af opslag i Facebook-stil, men hvis du vil have en pænt pagineret liste med mulighed for at gå til f.eks. side 42, får du det meget sværere. Der er selvfølgelig måder at omgå det på, men det er, hvad det er - omgåelser.
Ville vi gøre det igen?
Med alle de problemer og forskelle, der er nævnt ovenfor, tror du sikkert, at vi behandler GraphQL som et eksperiment, der er gået i vasken og er gået direkte tilbage til REST API'er. Det er ikke sandt. Om noget arbejder vi på at bruge GraphQL mere bredt i projekter i hele organisationen. Det er en fantastisk teknologi, som har gjort vores arbejde nemmere og bedre. Vi investerede dog oprindeligt i GraphQL uden helt at være klar over, hvilken slags vokseværk vi skulle igennem.
Hvis du tror, at GraphQL kunne være noget for dig, vil jeg opfordre dig til at tage springet. Giv dig selv god tid og plads til at fejle, og du vil høste fordelene inden længe!
Læs også her:
– Hvordan håndterer man effektivt eksterne udviklere? En guide til CTO'er
– Python vs. Ruby? Hvilken teknologi skal du bruge til produktudvikling?
– En hurtig guide til at opbygge og udvikle din egen markedsplads. Hvad er værd at vide?