Wiele firm przeszło na GraphQL do budowania swoich interfejsów API. I mają powód - to rewolucyjny sposób myślenia o danych.
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.
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.
Opracowanie działającego interfejsu API GraphQL wymaga dwóch komponentów: serwera i klienta.
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.
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:
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?
Więc czego potrzebujemy do stworzenia API GraphQL?
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.
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!”
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.
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.
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.
Jesteśmy gotowi na testy!
npm index.js
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 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 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.