Jak zacząć z GraphQL
Wiele firm przeszło na GraphQL do budowania swoich interfejsów API. I mają powód - to rewolucyjny sposób myślenia o danych.
Początki GraphQL i dlaczego jest tak przydatny
GraphQL pochodzi z Facebooka, który wewnętrznie szukał sposobu na zwiększenie wydajności ładowania newsfeedu w telefonach komórkowych. Korzystając z tradycyjnej struktury REST API, newsfeed wysyłał zapytania do wielu endpointów API, aby uzyskać wszystkie potrzebne dane. W tym czasie wywołania API również ładowały dodatkowe dane, których newsfeed wcale nie potrzebował. Dodatkowo po otrzymaniu całości inżynierowie front-endowi nadal musieli analizować dane, aby znaleźć poszukiwane pola.
Inżynierowie z Facebooka zastanawiali się:
Co by było, gdybyśmy mogli napisać język zapytań, który mógłby określić wszystkie potrzebne informacje w jednym żądaniu API?
GraphQL jest wynikiem tego pomysłu. Mapuje relacje między obiektami w bazie danych, tworząc grafy. Następnie zaprojektowali język zapytań do nawigowania po tej mapie relacji. Stąd nazwa GraphQL.
Dzięki dodaniu języka zapytań, interfejsy API GraphQL mogą teraz przyjmować wszystkie żądania przychodzące, w jednym punkcie końcowym. Następnie pobierają i zwracają żądane dane i tylko je. Koniec z wysypem informacji, z których nie korzystasz.
Specyfikacja, a nie implementacja
Bardzo ważne jest to, że Facebook postanowił udostępnić kod źródłowy GraphQL jako specyfikację.
Oznacza to, że może być zaimplementowany w dowolnym języku programowania. Dopóki implementacja analizuje zapytania, schematy struktury itp. w określony sposób, będzie działać dobrze z każdą inną aplikacją GraphQL. Faktycznie, istnieją dziesiątki implementacji GraphQL w każdym głównym języku programowania.
W tym artykule użyjemy referencyjnej implementacji GraphQL napisanej w JavaScript, ale te same podstawowe zasady obowiązują w każdym języku. Możesz rzucić okiem na pełną listę implementacji GraphQL, aby znaleźć swój ulubiony język.
Podstawowa architektura
Opracowanie działającego interfejsu API GraphQL wymaga dwóch komponentów: serwera i klienta.
- Serwer obsługuje przychodzące zapytania, analizuje je, pobiera dane przy użyciu zdefiniowanego schematu i zwraca odpowiedź, zwykle w JSON.
- Klient umożliwia Twojej aplikacji komunikację z serwerem. Chociaż możesz po prostu wysłać zwykłe żądanie POST do punktu końcowego GraphQL, uzyskasz znacznie większą funkcjonalność, jeśli używasz klienta GraphQL do pomocy w wysyłaniu zapytań.
Budowanie API GraphQL może być bardziej intensywne niż budowanie REST API. Jednak korzyści w zakresie szybkości i użyteczności mogą nadrobić to w aplikacjach złożonych lub wysokowydajnych.
Jak wygląda GraphQL
Naszym celem dla naszego API jest wysłanie zapytania GraphQL i uzyskanie odpowiedzi. Zobaczmy więc, jak to wygląda. Pamiętaj, że GraphQL to też język. Nie jest trudny do nauki, a większość zapytań jest bardzo intuicyjna.
Wyobraźmy sobie, że mamy bazę danych, która zawiera informacje o lotach i pasażerach. W GraphQL możemy zapytać o lot w następujący sposób:
{
flight(id: "1234") {
origin
destination
}
}
Jest to sposób, w jaki GraphQL powie: „podaj początek i cel lotu 1234”. W odpowiedzi otrzymamy:
{
"data": {
"flight": {
"origin": "DFW",
"destination": "MKE"
}
}
}
Uwaga:
- Otrzymujemy dokładnie to, o co prosiliśmy - nie mniej i nie więcej.
- Otrzymujemy również odpowiedź w dokładnie tym samym formacie, co oryginalne zapytanie, które wysłaliśmy.
Oto główne cechy interfejsu API GraphQL. Właśnie to sprawia, że GraphQL jest tak szybki i wydajny.
Ale to nie wszystko, co możemy w nim zrobić. Powiedzmy, że chcemy uzyskać informacje o pasażerach podczas lotu:
{
flight(id: "1234") {
origin
destination
passengers {
name
}
}
}
Teraz GraphQL przejdzie przez wykres zależności między tym lotem a jego pasażerami. Otrzymamy listę pasażerów:
{
"data": {
"flight": {
"origin": "DFW",
"destination": "MKE",
"passengers": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "R2-D2"
}
]
}
}
}
Super, możemy natychmiast zobaczyć wszystkich pasażerów tego lotu za pomocą jednego zapytania do API.
Bardziej ciekawi mnie, dlaczego Han, Luke i R2 latają samolotem lokalnym, ale słyszałem, że Milwaukee jest piękne o tej porze roku.
Ponieważ GraphQL interpretuje dane jako graf, możemy również nawigować po nim w innym kierunku.
{
person(name: "Luke Skywalker") {
passport_number
flights {
id
date
origin
destination
}
}
Teraz możemy zobaczyć, jakie loty zarezerwował Luke:
{
"data": {
"person": {
"passport_number": 78120935,
"flights": [
{
"id": "1234",
"date": "2019-05-24",
"origin": "DFW",
"destination": "MKE"
},
{
"id": "2621",
"date": "2019-07-05",
"origin": "MKE",
"destination": "DFW"
}
]
}
}
}
Wow, spędzi w Milwaukee ponad miesiąc! Ciekawe, co on tam robi?
Lista rzeczy do zrobienia
Więc czego potrzebujemy do stworzenia API GraphQL?
- Wybierz framework, w którym zaimplementujesz serwer GraphQL. My użyjemy Express.
- Zdefiniuj schemat, aby GraphQL wiedział, jak zrobić routing przychodzących zapytań.
- Stwórz funkcje, które obsłużą zapytania i powiedzą GraphQL co zwrócić.
- Stwórz endpoint
- Napisz zapytanie po stronie klienta, które pobiera dane
Ten samouczek nie obejmie wszystkich sposobów korzystania z GraphQL na front-endzie, ale pamiętaj, że dobrze integruje się ze wszystkimi nowoczesnymi frameworkami.
Ostatecznie większość zastosowań GraphQL wiąże się z rozmową z bazą danych. W tym samouczku nie omówimy dodawania bazy danych do Express i umożliwienia GraphQL zapytania i aktualizacji tej bazy danych. To jest temat na zupełnie inny tutorial.
Pierwszy krok: Implementacja serwera
Najpierw musimy położyć podwaliny pod nasze API. Będziesz musiał zainstalować nodejs i npm, aby kontynuować dalej korzystanie z tego samouczka.
Zbudujmy prościutki serwer Express. Zacznij od zainicjowania npm:
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (graphql-medium)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /home/bennett/Repos/graphql-medium/package.json:
{
"name": "graphql-medium",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this OK? (yes)
Naciśnij Enter, aby przejść przez proces inicjalizacji. Jeśli chcesz, możesz wrócić i edytować plik package.json
później.
Następnie zainstalujmy bibliotekę Express, GraphQL i Express-GraphQL:
$ npm install express express-graphql graphql
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN [email protected] No description
npm WARN [email protected] No repository field.
+ [email protected]
+ [email protected]
+ [email protected]
added 53 packages from 38 contributors and audited 151 packages in 6.169s
found 0 vulnerabilities
Teraz utworzymy nowy plik o nazwie index.js
i utworzymy tam nowy prosty serwer Express:
// index.js
const express = require('express');
const app = express();
app.get('/', function(req, res) {
res.send('Express is working!')
});
app.listen(4000, function() {
console.log('Listening on port 4000')
});
Spróbuj uruchomić node index.js
. Powinien pojawić się komunikat “listening on port 4000”, a jeśli odwiedzisz http: // localhost: 4000 / , zobaczysz komunikat że „Express działa!”
Drugi krok: Dodaj GraphQL i zdefiniuj schemę
Już zainstalowaliśmy pakiet GraphQL npm. Teraz użyjmy go.
Najpierw musimy zaimportować niezbędne bloki konstrukcyjne:
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');
Następnie użyjemy tych bloków. Zacznijmy od zdefiniowania schematu naszego API GraphQL. Jak powinno wyglądać zapytanie przychodzące?
Na razie po prostu zdefiniujmy schemat “hello world”, aby upewnić się, że wszystko działa:
let schema = buildSchema(`
type Query {
hello: String
}
`);
Ten prosty schemat informuje GraphQL, że gdy ktoś wysyła zapytanie o „hello”, ten musi zwrócić string.
Zwróć uwagę na te małe odwrócone apostrofy(`). Wskazują, że używamy literału szablonu JavaScript. Zasadniczo używamy ich, aby powiedzieć JavaScript, że zamierzamy napisać coś w innym języku - języku zapytań GraphQL.
Trzeci krok: Rozwiązywanie zapytań
Tak więc, gdy ktoś przesyła zapytanie do hello
, wiemy, że w końcu zwrócimy ciąg znaków. To jest zdefiniowane w naszym schemacie.
Teraz musimy dokładnie powiedzieć GraphQL, jaki string powinien zwrócić. Ustalenie, jakie dane są do zwrócenia na podstawie przychodzącego zapytania, to zadanie „resolvera” w GraphQL.
W tym przykładzie resolver jest prosty. To dosłownie ciąg „Hello world”
return 'Hello world!';
Musimy jednak opakować tę informację w funkcję, która może zostać wywołana wiele razy, za każdym razem, gdy ktoś wykona zapytanie hello:
function() {
return 'Hello world!';
}
Owszem, Hello
może nie być jedynym typem zapytania, który implementujemy. W przyszłości możemy również dołączyć „punkty końcowe” dla innych funkcji. Powinniśmy więc upewnić się, że to właśnie utworzona funkcja została zmapowana na “hello” i zapisana w obiekcie obok wszystkich innych funkcji rozwiązujących zapytania do naszego API.
let root = {
hello: function() {
return 'Hello world!';
},
}
To konwencjonalne, że obiekt, który zawiera wszystkie resolvery, nazywamy root
, ale możesz nazwać go jak chcesz.
Czwarty krok: Konfiguracja punktu końcowego
Uważni czytelnicy zauważą, że zaimportowaliśmy graphqlHTTP
w kroku 2, ale jeszcze go nie używaliśmy. Pora to zrobić. Mamy teraz wszystko dla naszego serwera GraphQL. Musimy go wystawić za pośrednictwem punktu końcowego URL.
W Expressie stworzymy nową nowy wpis w routingu do obsługi interfejsu API GraphQL:
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
Schema i root to zmienne, które zdefiniowaliśmy w krokach drugim i trzecim.
graphiql jest użytecznym narzędziem wizualnym instalowanym wraz z GraphQL. Jak zobaczymy za chwilę, ułatwia sprawdzenie, jak działa Twój interfejs API.
Oto końcowy stan naszego kodu źródłowego dla naszego serwera GraphQL.
Piąty krok: Uruchom go i napisz zapytanie
Jesteśmy gotowi na testy!
- Uruchom aplikację za pomocą
npm index.js
- Przejdź do http: // localhost: 4000 / graphql
Powinieneś zobaczyć interfejs graphiql:
Możemy teraz użyć tego interfejsu, aby upewnić się, że nasze API działa!
Napiszmy zapytanie. Te będzie bardzo proste. Nasze zapytania GraphQL zawsze zawijamy w nawiasy klamrowe. Następnie określamy obiekt schematu, o który pytamy, a następnie wszelkie atrybuty, które chcemy pobrać.
W tym przypadku do pobrania jest tylko jedna rzecz w naszym interfejsie API:
{
hello
}
Po kliknięciu przycisku wysyłania zobaczysz:
{
"data": {
"hello": "Hello world!"
}
}
Wszystko działa!
Dodawanie kolejnych punktów końcowych
Dodawanie punktów końcowych do interfejsu API jest tak proste, jak definiowanie nowych pól w schemacie, a następnie dodawanie funkcji resolvera do root
. Stopniowo zapytania stają się coraz bardziej złożone. Polecam ten poradnik na temat udowania API do rzucania kostkami z oficjalnej dokumentacji, jako następny krok.
GraphQL, FTW
GraphQL jest niesamowity i szybko się rozwija. W nadchodzących latach może stać się wszechobecną technologią dla API.
Mam nadzieję, że ten przewodnik dał Ci dobre wprowadzenie do tego, jak i dlaczego możesz używać GraphQL w swoich projektach.
Oryginalny tekst w języku angielskim możesz przeczytać tutaj.