Vi skriver 2020. Teamet ditt går mer og mer i retning av å bygge applikasjoner med én side, eller i det minste inkludere rike komponenter i vanlige applikasjoner med flere sider. [GraphQL](https://graphql.org/) er [over to år gammelt](https://en.wikipedia.org/wiki/GraphQL) nå, noe som etter JavaScript-økosystemstandarder kan anses som modent. Vi følte oss litt eventyrlystne, så vi droppet de vanlige JSON-API-ene og kastet oss rett ut i det - her er hva vi lærte.
Det er 2020. Din team i økende grad går i retning av å bygge applikasjoner med én side, eller i det minste inkludere rike komponenter i vanlige flersidige applikasjoner. [GraphQL](https://graphql.org/) er [over to år gammel](https://en.wikipedia.org/wiki/GraphQL) nå, noe som av JavaScript økosystemstandarder kan anses som modne. Vi følte oss litt eventyrlystne, så vi droppet de vanlige JSON-API-ene og kastet oss rett ut i det - her er hva vi fant ut.
Du trenger en GraphQL-server
I de fleste rammeverk som brukes for webutviklinger verktøyene for å bygge et JSON-API allerede tilgjengelige. Du kan bygge en rutestruktur og enkelt godta noen GETs og POSTs, og deretter sende ut et JSON-svar. Ruby on Rails har til og med en spesiell prosjekt som fjerner de vanlige HTML-renderingstingene og i stedet legger et solid grunnlag for API-er. En dyktig utvikler som bruker moderne verktøy, kan dermed lage en backend på bokstavelig talt få minutter.
Slik er det ikke med GraphQL. Selv om det finnes serverbiblioteker for mange språk... du fortsatt pådrar deg en hastighetsstraff rett ut av porten - rett og slett ved å måtte finne ut hva som er riktig for ditt økosystem. Personlig liker jeg heller ikke at begrepet "server" brukes for å beskrive et bibliotek som kan introduseres i et prosjekt.
Det finnes bare ett endepunkt
I årenes løp ble vi vant til en bestemt måte å tenke på når det gjaldt API-struktur. På det mest grunnleggende nivået fulgte vi ganske enkelt REST-praksis. Det betyr at vi oppretter flere endepunkter per logisk modell i appen vår. Det er en struktur som er lett å forstå for både API-forfattere og -brukere. Det gir også godt avgrensede metoder i backend, noe som gjør det enklere å resonnere om kode like enkelt som om selve API-et. Denne strukturen er også enkel å navngi, f.eks. i forbindelse med API-versjonering.
GraphQL benytter bare ett enkelt endepunkt, vanligvis /graphql
. Alle forespørsler til API-et ditt kommer som en POST-forespørsel til dette endepunktet, og derfra er det GraphQL-serverens ansvar å finne ut hva klienten vil ha og svare på riktig måte.
Ved første øyekast føles det uhåndterlig: Tenk deg å prøve å gjøre alt i et JSON API med ett enkelt endepunkt! Det begynner imidlertid å gi mening etter hvert som API-et ditt modnes og noen ting erstattes av andre. Deprecation i klassiske API-er gjøres vanligvis på navneromsnivå, ved å flytte fra v1
til v2
. GraphQL gir mye mer kontroll, helt opp til å utelate et enkelt felt. Tenk deg å kunne fortelle en REST API-kunde at du ikke vil at de skal bruke navn
feltet og å bruke fancy_name
i stedet! Det viser seg at det som først føltes tungvint, faktisk er en av de beste funksjonene.
Alt er skrevet på maskin
JSON har egentlig ikke så mange typemuligheter. Det finnes strenger, tall, matriser og objekter. Utover det har du ikke mye flaks. I GraphQL derimot, begynner og slutter alt med typer, ettersom til og med roten Query og Mutation er nettopp det - typer. GraphQL DSL håndhever typekontroll på både serveren og klienten, noe som forhindrer alle slags ubehagelige overraskelser.
Dette er svært viktig, spesielt ettersom SPA-ene i stadig større grad blir typekontrollert selv, enten det er ved hjelp av TypeScript eller alternativer som Flow. GraphQL gjør det enkelt å introdusere komplekse og sammensatte typer på toppen av standardverdiene, og det blir raskt en selvfølge for utviklere på både backend og frontend.
Les mer om dette: Tester JavaScript ... med Ruby?!
Dokumentasjonen er innebygd
I et klassisk JSON-API kan dokumentasjonen være en ettertanke. Og selv om den ikke er det, finnes det mange metoder å velge mellom. Skal vi bruke et skjema som OpenAPI? Konverterer vi det deretter til lesbar form med verktøy som Swagger? Eller dumper vi bare en hel haug med Markdown-filer et sted? Selv om dette problemet har blitt løst flere ganger, krever det fortsatt bevisst tenkning og innsats fra teamet - først for å bygge dokumentene, deretter for å holde dem oppdatert og spredt. Det er et enda mer komplekst problem når API-et har flere seksjoner som bare er tilgjengelige for f.eks. visse brukerroller.
I GraphQL er dokumentasjon en førsteklasses borger, ettersom de fleste servere gir mulighet for å dokumentere typer og forespørsler på stedet. Siden tidlig i 2018 har GraphQL Schema Definition Language blitt en del av den offisielle spesifikasjonen, så det finnes nøyaktig én måte å dokumentere et GraphQL API på. Siden GraphQL gjør det mulig å definere synligheten til visse deler av grafen, blir de brukerne som ikke skal ha tilgang, automatisk forhindret fra å se dokumenter for det de ikke har tilgang til. Det har vært en stor fordel for teamet å ha tatt denne avgjørelsen og å ha klare retningslinjer.
Det finnes bare to typer handlinger
I motsetning til HTTPs GET, POST, PUT, PATCH og DELETE finnes det bare to typer handlinger i GraphQL: Spørringer og mutasjoner. Hovedforskjellen er at mutasjoner kan og vil endre systemets tilstand, mens spørringer kun passivt vil lese ut data.
Jeg må innrømme at jeg fortsatt er usikker på dette. Jeg liker HTTPs overflod av verb for å samhandle med ressurser og kunne bruke akkurat det riktige verktøyet for jobben. GraphQL gjør det enklere å ta seg av de vanskelige tilfellene der et av HTTP-verbene ikke passet helt, men straffen er å måtte tenke på hva en bestemt mutasjon faktisk vil påvirke. Det kan også påpekes at siden det ikke finnes noen innebygd standard navnekonvensjon, må du lage interne stilguider eller risikere å bygge et inkonsekvent rot.
Du trenger stort sett en klient
Det er superenkelt å samhandle med REST API-er over HTTP i vanilla JavaScript, og enda enklere med den moderne hente
API. For GraphQL bør du derimot bruke et klientbibliotek hvis du vil ha virkelig god ytelse. Det er ikke umulig å samhandle med et GraphQL API ved hjelp av vanilje JavaScript - det er tross alt bare POST-forespørsler. Det vil imidlertid ikke fungere å bruke gamle webteknologier som caching av forespørsler for vanlige API-anrop, ettersom POST-forespørsler vanligvis ikke caches.
Alle fornuftige GraphQL-klienter implementerer en caching-mekanisme for resultater på klientsiden, og mange flere funksjoner. Takket være alle disse valgene er det en helt uoverkommelig oppgave å håndrullere en konfigurasjon for en GraphQL-klient på inngangsnivå. Når du begynner med GraphQL, anbefaler jeg spesielt å ta en titt på Apollo-Boost siden det kommer med svært rimelige standardinnstillinger.
Kunden plukker ut dataene
Vi har alle vært der: Vi henter ut en liste med data fra API-et, og den mangler et viktig felt om en relatert modell. Deretter implementerer vi et hack som involverer N+1 forespørsler, mens vi klager på backend-utviklerne som skynder seg rundt for å legge det til. Det er vanligvis ikke tilfelle med et godt implementert GraphQL API, siden vi bare kan dykke så dypt ned i dataene som vi vil. Trenger du å se adressen til en kunde på en ordre i denne batchen? Ikke noe problem - i hvert fall i teorien, noe som leder oss til...
Kompleksitet er vanskeligere å forutse
Når du designer GraphQL fra backend-siden, kan det være vanskelig å tenke på hvor dypt en klient kan dykke ned i grafen. Det finnes mange måter å instrumentere og observere bruken av grafen på, og etter å ha latt frontend-kollegene dine leke seg en stund, kan du begynne å se noen lange spørringer som utfører ganske fantasifulle lesninger i datalageret ditt. I et REST API er dette enklere å kontrollere, siden du enkelt kan angi omfanget av data som skal åpnes i en enkelt forespørsel. Ofte kan denne manglende kompleksiteten bite deg hardt når du lanserer til produksjon. Mange ganger er det heller ikke åpenbart hvordan man skal komme seg ut av dette hullet man har gravd for seg selv.
Nummererte sider er veldig vanskelig
Dette er egentlig en spydighet. Du kan definitivt føle at GraphQL ble designet på og for Facebook ved å se på hvordan den tiltenkte pagineringsmekanismen fungerer. De såkalte Connections er i bunn og grunn endeløse strømmer av grafkanter, der navigasjonen skjer gjennom markører i stedet for de mer klassiske sidene. Det er lett å se hvordan dette passer med en endeløs feed av innlegg i Facebook-stil, men hvis du vil ha en oversiktlig paginert liste med mulighet til å gå til for eksempel side 42, blir det mye vanskeligere. Det finnes selvfølgelig måter å omgå dette på, men det er nettopp det de er - omgåelser.
Ville vi gjort det igjen?
Med alle de innvendingene og forskjellene som er nevnt ovenfor, tror du sikkert at vi ser på GraphQL som et eksperiment som har slått feil og gått rett tilbake til REST API-er. Det er ikke sant. Tvert imot jobber vi med å bruke GraphQL i større grad i prosjekter i hele organisasjonen. Det er en fantastisk teknologi som har gjort jobben vår enklere og bedre. Vi investerte imidlertid i GraphQL uten å være helt klar over hva slags voksesmerter vi ville komme til å gå gjennom.
Hvis du tror GraphQL kan være noe for deg, oppfordrer jeg deg til å ta steget. Gi deg selv god tid og rom til å feile, så vil du høste fordelene innen kort tid!
Les også:
– Hvordan lede eksterne utviklere på en effektiv måte? En guide for CTO-er
– Python vs. Ruby? Hvilken teknologi bør du bruke til produktutvikling?
– En rask guide til hvordan du bygger og utvikler din egen markedsplass. Hva er verdt å vite?