Het is 2020. Je team neigt steeds meer naar het bouwen van applicaties met één pagina, of in ieder geval het opnemen van rijke componenten binnen reguliere applicaties met meerdere pagina's. [GraphQL](https://graphql.org/) is nu [meer dan twee jaar oud](https://en.wikipedia.org/wiki/GraphQL), wat volgens de normen van het JavaScript ecosysteem als volwassen kan worden beschouwd. We voelden ons een beetje avontuurlijk, dus we zagen af van de gebruikelijke JSON API's en doken er meteen in - dit is wat we hebben geleerd.
Het is 2020. Uw team richt zich steeds meer op het bouwen van toepassingen met één pagina, of op zijn minst op het opnemen van rijke componenten binnen reguliere toepassingen met meerdere pagina's. [GraphQL](https://graphql.org/) is nu [meer dan twee jaar oud](https://en.wikipedia.org/wiki/GraphQL), wat door JavaScript standaarden voor ecosystemen als volwassen kunnen worden beschouwd. We voelden ons een beetje avontuurlijk, dus we zagen af van de gebruikelijke JSON API's en doken er meteen in - dit is wat we hebben geleerd.
Je hebt een GraphQL-server nodig
In de meeste raamwerken die gebruikt worden voor webontwikkelingDe tools om een JSON API te bouwen zijn er al. Je kunt een routestructuur bouwen en eenvoudig enkele GET's en POST's accepteren en vervolgens een JSON antwoord uitvoeren. Ruby on Rails heeft zelfs een speciale project setup-switch die afziet van de gebruikelijke HTML-rendering goodies en er een solide basis voor API's voor in de plaats zet. Wat volgt is dat een ervaren ontwikkelaar met moderne tools een backend in letterlijk enkele minuten in elkaar kan flansen.
Dat geldt niet voor GraphQL. Hoewel er serverbibliotheken zijn voor vele talendan heb je nog steeds te maken met een snelheidsnadeel - simpelweg omdat je moet uitzoeken wat het beste is voor jouw ecosysteem. Op een meer persoonlijke noot, ik ben ook niet dol op de term "server" die wordt gebruikt om een bibliotheek te beschrijven die kan worden geïntroduceerd in een project.
Er is maar één eindpunt
In de loop der jaren zijn we gewend geraakt aan een bepaalde manier van denken over API-structuur. Op het meest basale niveau volgden we gewoon REST-praktijken. Dat betekende dat we meerdere endpoints per logisch model in onze app maakten. Het is een structuur die gemakkelijk te begrijpen is voor zowel de API-auteurs als de gebruikers. Het levert ook goed gescoped methoden op in de backend, waardoor redeneren over de code net zo gemakkelijk als over de API zelf. Deze structuur is ook gemakkelijk te voorzien van een naamruimte, bijvoorbeeld voor de doeleinden van API-versiebeheer.
GraphQL gebruikt slechts één eindpunt, gewoonlijk /graphql
. Elk verzoek naar je API komt als een POST verzoek aan op dat eindpunt en vanaf daar is het de verantwoordelijkheid van de GraphQL server om uit te zoeken wat de klant wil en op de juiste manier te reageren.
Op het eerste gezicht voelt het onhandig: stel je voor dat je alles in een JSON API probeert te doen met een enkel eindpunt! Het begint echter al snel zinvol te worden als je API volwassener wordt en sommige dingen worden vervangen door andere. Deprecatie in klassieke API's wordt meestal gedaan op het niveau van de naamruimte, waarbij van v1
naar v2
. GraphQL biedt veel meer controle, tot het depreciëren van een enkel veld. Stel je voor dat je een REST API gebruiker kunt vertellen dat je niet wilt dat ze de naam
veld en om fantasienaam
in plaats daarvan! Het blijkt dat wat in eerste instantie onhandig aanvoelde, eigenlijk een van de beste functies is.
Alles is getypt
JSON heeft niet echt veel typmogelijkheden. Er zijn strings, getallen, arrays en objecten. Verder heb je pech. In GraphQL daarentegen begint en eindigt alles met types, want zelfs de basis Query en Mutation zijn gewoon dat - types. De GraphQL DSL dwingt typecontrole af op zowel de server als de client, waardoor allerlei onaangename verrassingen worden voorkomen.
Dit is erg belangrijk, vooral omdat SPA's steeds vaker zelf worden gecontroleerd, of dit nu gebeurt met TypeScript of met alternatieven zoals Flow. GraphQL maakt het eenvoudig om complexe en samengestelde typen te introduceren bovenop de standaardwaarden en het wordt snel een tweede natuur voor ontwikkelaars op zowel de backend als de frontend.
Lees meer: Testen van JavaScript...met Ruby?!
De documenten zijn ingebouwd
In een klassieke JSON API kan de documentatie een bijzaak zijn. En zelfs als dat niet zo is, zijn er veel methoden om uit te kiezen. Gebruiken we een schema zoals OpenAPI? Converteren we het dan naar een menselijk leesbare vorm met tools zoals Swagger? Of dumpen we gewoon een heleboel Markdown-bestanden ergens? Hoewel dit probleem al meerdere keren is opgelost, vereist het nog steeds bewust nadenken en inspanning van het team - eerst om de documenten te bouwen, dan om ze bijgewerkt te houden en te verspreiden. Het is een nog complexer probleem als de API verschillende secties heeft die alleen toegankelijk zijn voor bijvoorbeeld bepaalde gebruikersrollen.
In GraphQL is documentatie een eersteklas burger, omdat de meeste servers het mogelijk maken om je types en requests te documenteren. Sinds begin 2018 is de GraphQL Schema Definition Language onderdeel van de officiële spec, dus er is precies één manier om een GraphQL API te documenteren. En omdat GraphQL het mogelijk maakt om de zichtbaarheid van bepaalde delen van de grafiek te definiëren, wordt automatisch voorkomen dat gebruikers die dat niet zouden moeten doen, docs te zien krijgen voor datgene waar ze geen toegang toe hebben. De beslissing is genomen en duidelijke richtlijnen zijn een grote zegen voor het team.
Er zijn slechts twee soorten acties
In tegenstelling tot HTTP's GET, POST, PUT, PATCH en DELETE zijn er slechts twee soorten acties in GraphQL: Queries en Mutaties. Het belangrijkste verschil is dat Mutaties de toestand van het systeem kunnen en zullen veranderen, terwijl Queries alleen passief gegevens uitlezen.
Ik geef toe dat ik hier nog steeds niet helemaal zeker van ben. Ik geniet van HTTP's overvloed aan werkwoorden voor interactie met bronnen en de mogelijkheid om precies het juiste gereedschap voor de klus te gebruiken. GraphQL maakt het gemakkelijker om die harige gevallen op te lossen waar een van de HTTP werkwoorden niet precies past, maar heeft als nadeel dat je moet nadenken over wat een bepaalde mutatie eigenlijk zal beïnvloeden. Er kan ook gezegd worden dat omdat er niet echt een ingebouwde standaard naamgevingsconventie is, je interne stijlgidsen moet opstellen of het risico loopt een inconsistente puinhoop te bouwen.
Je hebt een klant nodig
Interactie met REST API's over HTTP is supergemakkelijk in vanilla JavaScript, en nog gemakkelijker met de moderne ophalen
API. Voor GraphQL daarentegen wil je een client library gebruiken als je echt goede prestaties wilt. Het is niet onmogelijk om te communiceren met een GraphQL API met gewoon vanille JavaScript - het zijn tenslotte gewoon POST verzoeken. Het gebruik van al lang bestaande webtechnologieën zoals request caching voor veelvoorkomende API-aanroepen zal echter niet werken, omdat POST-verzoeken over het algemeen niet in de cache worden opgeslagen.
Elke redelijke GraphQL client implementeert een client-side resultaat caching mechanisme, en nog veel meer functies. Dankzij al deze keuzes is het met de hand configureren van een GraphQL client op instapniveau een compleet verbijsterende taak. Als je begint met GraphQL raad ik je vooral aan om te kijken naar Apollo-Boost omdat het wordt geleverd met zeer redelijke standaardinstellingen.
Klant kiest de gegevens
We hebben het allemaal wel eens meegemaakt: we haalden een lijst met gegevens uit de API en er ontbrak een cruciaal veld over een gerelateerd model. We implementeren dan een hack waarbij we N+1 requests moeten doen, terwijl we mopperen op de backend ontwikkelaars die het snel toevoegen. Dat is meestal niet het geval bij een goed geïmplementeerde GraphQL API, omdat we gewoon zo diep in de gegevens kunnen duiken als we willen. Wil je het adres van een klant zien op een bestelling in deze batch? Geen probleem - althans in theorie, wat ons mooi brengt bij...
Complexiteit is moeilijker te voorzien
Bij het ontwerpen van GraphQL vanuit de back-end kant kan het moeilijk zijn om na te denken over de diepte die een klant in de grafiek kan gaan. Er zijn veel manieren om het gebruik van je grafiek te instrumenteren en te observeren, en nadat je je front-end collega's een tijdje hebt laten spelen, kun je lange queries zien die nogal fantasierijke reads uitvoeren op je data store. In een REST API is dit eenvoudiger te controleren omdat je eenvoudig de omvang van de gegevens die worden benaderd in een enkel verzoek kunt aangeven. Vaak komt deze gemiste complexiteit hard aan zodra je het vrijgeeft voor productie. Vaak is het ook niet duidelijk hoe je uit dit gat kunt komen dat je voor jezelf hebt gegraven.
Genummerde pagina's zijn echt moeilijk
Dit is eigenlijk een opmerking met een knipoog. Je kunt zeker voelen dat GraphQL is ontworpen voor en door Facebook door te kijken naar de manier waarop het beoogde paginagemechanisme werkt. De zogenaamde Connections zijn in feite eindeloze stromen van grafiekranden, waarop wordt genavigeerd via cursors in plaats van de meer klassieke pagina's. Het is makkelijk te zien hoe dat past bij een eindeloze feed van berichten in Facebook-stijl, maar als je een netjes gepagineerde lijst wilt met de mogelijkheid om naar bijvoorbeeld pagina 42 te gaan, zul je het veel moeilijker hebben. Er zijn natuurlijk manieren om daar omheen te werken, maar dat is wat ze zijn - workarounds.
Zouden we het weer doen?
Met alle bezwaren en verschillen die hierboven zijn opgesomd denk je waarschijnlijk dat we GraphQL behandelen als een mislukt experiment en meteen teruggaan naar REST API's. Dat is niet waar. We werken juist aan een breder gebruik van GraphQL in projecten in de hele organisatie. Het is een geweldige technologie die ons werk gemakkelijker en beter heeft gemaakt. We hebben echter in eerste instantie geïnvesteerd in GraphQL zonder ons volledig te realiseren wat voor groeipijnen we zouden moeten doormaken.
Als je denkt dat GraphQL iets voor jou is, moedig ik je aan om de sprong te wagen. Geef jezelf voldoende tijd en ruimte om veilig te falen, en je zult snel de vruchten plukken!
Lees ook:
– Hoe ontwikkelaars op afstand effectief beheren? De gids voor CTO's
– Python vs. Ruby? Welke technologie moet je gebruiken voor productontwikkeling?
– Een beknopte gids voor het bouwen en ontwikkelen van je eigen marktplaats. Wat is de moeite waard om te weten?