Å komme inn GraphQL med AWS AppSync

0
23

GraphQL blir stadig mer populært. Problemet er at hvis du er en front-end utvikler, du er bare halvparten av veien dit. GraphQL er ikke bare en klient teknologi. Serveren har også å være gjennomført i henhold til spesifikasjon. Dette betyr at for å implementere GraphQL inn i søknaden din, må du lære, ikke bare GraphQL på fronten, men også GraphQL beste praksis, server-side utvikling, og alt som går langs med den på baksiden slutten.

Det vil komme en tid når du vil også nødt til å håndtere problemer som skalering på serveren, komplekse autorisasjon scenarier, ondsinnet spørsmål, og flere spørsmål som krever mer kompetanse og enda dypere kunnskap rundt hva som er tradisjonelt kategorisert som back-end utvikling.

Heldigvis har vi en rekke administrative back-end tjenesteleverandører i dag som gjør at front-end utviklere å bare bry deg om å implementere funksjoner på fronten uten å måtte hanskes med alle de tradisjonelle back-end arbeid.

Tjenester som Firebase (API) / AWS AppSync (database), Cloudinary (media), Algolia (søk) og Auth0 (autentisering) tillate oss å avlaste våre kompleks infrastruktur til en tredjeparts leverandør og i stedet fokusere på å levere verdi til sluttbrukere i form av nye funksjoner i stedet.

I denne opplæringen vil vi lære hvordan du kan dra nytte av AWS AppSync, et klart GraphQL service, for å bygge en full stack program uten å skrive en eneste linje med back-end-koden.

Mens rammene vi arbeider i er Reagere, begreper og API-kall vi skal bruke er framework-agnostisk og vil fungere den samme i Kantete, Vue, Reagerer Innfødte, Ionisk eller andre JavaScript-rammeverk eller program.

Vi vil være med å bygge en restaurant gjennomgang app. I dette programmet, vil vi være i stand til å opprette en restaurant, utsikt (over hav restauranter, opprette en anmeldelse for en restaurant, og vise anmeldelser for restaurant.

Verktøy og rammeverk som vi skal bruke er Reagere, AWS Forsterke, og AWS AppSync.

AWS Forsterke er et rammeverk som gir oss muligheten til å opprette og koble til cloud-tjenester, som autentisering, GraphQL Api-er, og Lambda funksjoner, blant andre ting. AWS AppSync er et klart GraphQL service.

Vi vil bruke Forsterke å opprette og koble til en AppSync API, og skriv deretter klientsiden Reagere kode for å samhandle med API.

Vis Repo

Komme i gang

Det første vi vil gjøre er å opprette en Reagerer prosjektet og flytte inn i den nye katalogen:

npx lage reagere-app ReactRestaurants

cd ReactRestaurants

Neste, vi vil installere avhengigheter som vi vil bruke for dette prosjektet. AWS Forsterke er JavaScript-bibliotek som vi vil bruke til å koble til API, og vi vil bruke Glamour for styling.

garn legge til aws-forsterke glamour

Det neste vi må gjøre er å installere og konfigurere Forsterke CLI:

npm installere -g @aws-forsterke/cli

forsterke konfigurere

Forsterke er konfigurere vil lede deg gjennom de nødvendige trinnene for å begynne å lage AWS tjenester på din konto. For en gjennomgang av hvordan du gjør dette, sjekk ut denne videoen.

Nå som programmet har blitt opprettet og Forsterke er klar til å gå, vi kan initialisere et nytt Forsterke prosjektet.

forsterke init

Forsterke init vil lede deg gjennom trinnene for å opprette en ny Forsterke prosjektet. Det vil be deg om dine ønskede navnet, miljø navn og tekst editor valg. Den CLI vil automatisk oppdage din Reagerer miljø og velg smart standardverdiene for resten av valg.

Å skape GraphQL API

Vi har initialisert en ny Forsterke prosjektet, kan vi nå legge til Restauranten Gjennomgang GraphQL API. For å legge til en ny tjeneste, vi kan kjøre forsterke legge til kommandoen.

forsterke legge til api

Dette vil lede oss gjennom følgende trinn for å hjelpe oss med å sette opp API:

? Vennligst velg fra en av de nedenfor nevnte tjenester GraphQL
? Gir API navn bigeats
? Velg en tillatelse type for API API-nøkkel
? Har du en forklart GraphQL skjema? N
? Ønsker du en guidet skjemaet skapelse? Y
? Hva som best beskriver ditt prosjekt: Enkelt objekt med felt
? Ønsker du å redigere skjemaet nå? Y

Den CLI skal nå åpne en grunnleggende skjema i tekst-editoren. Dette kommer til å bli skjemaet for våre GraphQL API.

Lim inn følgende skjema og lagre det.

// forsterke/backend/api/bigeats/skjema.graphql

skriv Restaurant @modellen {
id: ID!
by: String!
navn: String!
numRatings: Int
foto: String!
anmeldelser: [Anmeldelse] @tilkobling(navnet: “RestaurantReview”)
}
type Gjennomgang @modellen {
rating: Int!
tekst: String!
createdAt: String
restaurant: Restaurant! @tilkobling(navnet: “RestaurantReview”)
}

I dette skjemaet, vi holder på å lage to hovedtyper: Restaurant og Gjennomgang. Legg merke til at vi har @modellen og @forbindelse direktiver i vårt skjema.

Disse direktivene er en del av GraphQL Forvandle verktøy som er bygd inn i den Forsterke CLI. GraphQL Forvandle vil ta en base skjema innredet med direktiver og forvandle våre koden til en fullt funksjonell API som implementerer base data modell.

Hvis vi skulle spinne opp vår egen GraphQL API, så vi er helt nødt til å gjøre alt dette manuelt:

  1. Angi skjema
  2. Definere operasjoner mot skjemaet (spørsmål, mutasjoner, og abonnementer)
  3. Opprette data kilder
  4. Skriv resolvers at kartet mellom den skjema operasjoner og datakilder.

Med @- modellen direktivet, GraphQL Forvandle verktøyet vil stillaset ut alle skjema operasjoner, resolvers, og data kilder, slik at alt vi trenger å gjøre er å definere base-skjema (trinn 1). Den @forbindelse direktivet vil la oss modell relasjoner mellom modeller og stillaset ut riktig resolvers for relasjoner.

I vårt skjema, kan vi bruke @- tilkobling for å angi et forhold mellom Restaurant og Anmeldelser. Dette vil skape en unik identifikator for restaurant-ID-en for anmeldelse i den endelige generert skjema.

Vi har nå opprettet vår base skjema, kan vi skape API på vår konto.

forsterke trykk
? Er du sikker på at du vil fortsette? Ja
? Har du lyst til å generere kode for den nyopprettede GraphQL API Ja
? Velg kodegenerering språk målet javascript
? Angi filnavn mønster av graphql spørsmål, mutasjoner og abonnementer src/graphql/**/*.js
? Har du lyst til å generere/oppdater alle mulige GraphQL operasjoner – spørringer, mutasjoner og abonnementer Ja

Fordi vi skaper en GraphQL programmet, vi vanligvis ville ha behov for å skrive alle våre lokale GraphQL spørsmål, mutasjoner og abonnementer fra bunnen av. I stedet, CLI vil være å undersøke våre GraphQL skjema og deretter genererer alle definisjoner for oss og lagre dem lokalt for oss å bruke.

Når dette er fullført, back-end som har blitt opprettet og vi kan begynne å få tilgang til det fra vår Reagerer programmet.

Hvis du ønsker å vise din AppSync API i AWS dashboard, kan du gå https://console.aws.amazon.com/appsync og klikk på din API. Fra oversikten kan du se skjema, data kilder, og resolvers. Du kan også utføre spørringer og mutasjoner ved hjelp av den innebygde GraphQL redaktør.

Bygge Reagere klient

Nå som API er opprettet, og vi kan begynne å spørre for og lage data i vår API. Det vil være tre operasjonene som vi vil bruke til å samhandle med vår API:

  1. Opprette en ny restaurant
  2. Spørring for restauranter og sine vurderinger
  3. Opprette en anmeldelse for en restaurant

Før vi begynner å bygge app, la oss ta en titt på hvordan disse operasjonene vil se ut og fungere.

I samspill med AppSync GraphQL API

Når du arbeider med en GraphQL API, det er mange GraphQL klienter tilgjengelig.

Vi kan bruke alle GraphQL klient ville vi ønsker å samhandle med en AppSync GraphQL API, men det er to som er konfigurert spesielt for å arbeide mest lett. Disse er de Forsterke klient (hva vi vil bruke) og AWS AppSync JS SDK (tilsvarende API for å Apollo-klient).

Det Forsterke klienten er lik hente API i at det er løfte-basert og lett å resonnere om. Det Forsterke klienten ikke støtter frakoblede ut av boksen. Den AppSync SDK er mer kompleks, men støtter offline ut av boksen.

For å ringe AppSync API med å Forsterke, vi bruker API-kategori. Her er et eksempel på hvordan å ringe en spørring:

import { API, graphqlOperation } fra ‘aws-forsterke’
import * spørsmål fra ‘./graphql/spørringer’

const data = venter API.graphql(graphqlOperation(spørringer.listRestaurants))

For en mutasjon, det er veldig likt. Den eneste forskjellen er at vi trenger å gå i et annet argument for dataene vi sender i mutasjon:

import { API, graphqlOperation } fra ‘aws-forsterke’
import * som mutasjoner fra ‘./graphql/mutasjoner’

const restaurant = { name: “Babalu”, byen: “Jackson” }
const data = venter API.graphql(graphqlOperation(
mutasjoner.createRestaurant,
{ input: restaurant }
))

Vi bruker graphql metode fra API-kategorien til å ringe drift, pakke det i graphqlOperation, som analyserer GraphQL spørring strenger i standard GraphQL AST.

Vi vil bruke dette API-kategori for alle våre GraphQL drift i appen.

Her er repo som inneholder den endelige koden for dette prosjektet.

Konfigurere Reagere app med å Forsterke

Det første vi trenger å gjøre i våre app-er konfigurere den til å gjenkjenne vår Forsterke legitimasjon. Når vi opprettet vår API, CLI opprettet en ny fil som heter aws-exports.js i vår src-mappen.

Denne filen er opprettet og oppdatert for oss av CLI som vi opprette, oppdatere og slette tjenester. Denne filen er hva vi vil bruke til å konfigurere Reagere programmet til å få vite om våre tjenester.

For å konfigurere programmet ved å åpne opp src/index.js og legg til følgende kode:

import fra Forsterke ‘aws-forsterke’
import-config ‘./aws-eksport’
Forsterke.konfigurere(config)

Neste, vi vil opprette filer som vi trenger for våre komponenter. I src – katalogen, kan du opprette følgende filer:

  • Header.js
  • Restaurant.js
  • Review.js
  • CreateRestaurant.js
  • CreateReview.js

Å skape komponenter

Mens stiler er referert i kodebiter nedenfor, stil definisjoner har blitt utelatt for å gjøre utdrag mindre detaljert. For stil definisjoner, se det endelige prosjektet repo.

Neste, vi vil lage Header komponent ved å oppdatere src/Header.js.

// src/Header.js

import Reagere fra “reagerer’
import { css } fra ‘glamour’
const Header = ({ showCreateRestaurant }) => (
<div {…css-stiler.header)}>
<p {…css-stiler.tittelen)}>BigEats</p>
<div {…css-stiler.iconContainer)}>
<p {…css-stiler.ikonet)} onClick={showCreateRestaurant}>+</p>
</div>
</div>
)

eksport standard topp

Nå som vår Overskriften er opprettet, vi vil oppdatere src/App.js. Denne filen vil holde alle interaksjoner med API, så det er ganske stor. Vi vil definere metoder og sende dem ned som rekvisitter til komponenter som vil kalle dem.

// src/App.js

import Reagere, { Komponent } fra “reagerer’
import { API, graphqlOperation } fra ‘aws-forsterke’

import Overskriften fra”. /Header’
import Restauranter fra ‘./Restauranter’
import CreateRestaurant fra ‘./CreateRestaurant’
import CreateReview fra ‘./CreateReview’
import Anmeldelser fra ‘./Anmeldelser’
import * spørsmål fra ‘./graphql/spørringer’
import * som mutasjoner fra ‘./graphql/mutasjoner’

klasse App strekker seg Komponent {
tilstand = {
restauranter: [],
selectedRestaurant: {},
showCreateRestaurant: false,
showCreateReview: false,
showReviews: false
}
asynkron componentDidMount() {
try {
const rdata = venter API.graphql(graphqlOperation(spørringer.listRestaurants))
const { data: { listRestaurants: { items }}} = rdata
dette.setState({ restauranter: items })
} catch(err) {
– konsollen.logg(‘feilmelding: ‘, err)
}
}
viewReviews = (r) => {
dette.setState({ showReviews: true, selectedRestaurant: r })
}
createRestaurant = asynkron(restaurant) => {
dette.setState({
restauranter: […dette.staten.restauranter, restaurant]
})
try {
venter API.graphql(graphqlOperation(
mutasjoner.createRestaurant,
{input: restaurant}
))
} catch(err) {
– konsollen.logg(‘feil under oppretting av restaurant: ‘, err)
}
}
createReview = asynkron(id, input) => {
const restauranter = dette.staten.restauranter
const index = restauranter.findIndex(r => r.id === id)
restauranter[index].anmeldelser.elementer.trykk(inngang)
dette.setState({ restauranter })
venter API.graphql(graphqlOperation(mutasjoner.createReview, {input}))
}
closeModal = () => {
dette.setState({
showCreateRestaurant: false,
showCreateReview: false,
showReviews: false,
selectedRestaurant: {}
})
}
showCreateRestaurant = () => {
dette.setState({ showCreateRestaurant: true })
}
showCreateReview = r => {
dette.setState({ selectedRestaurant: r, showCreateReview: true })
}
render() {
retur (
<div>
<Header showCreateRestaurant={dette.showCreateRestaurant} />
<Restauranter
restauranter={dette.staten.restauranter}
showCreateReview={dette.showCreateReview}
viewReviews={dette.viewReviews}
/>
{
dette.staten.showCreateRestaurant && (
<CreateRestaurant
createRestaurant={dette.createRestaurant}
closeModal={dette.closeModal}
/>
)
}
{
dette.staten.showCreateReview && (
<CreateReview
createReview={dette.createReview}
closeModal={dette.closeModal}
restauranten={dette.staten.selectedRestaurant}
/>
)
}
{
dette.staten.showReviews && (
<Anmeldelser
selectedRestaurant={dette.staten.selectedRestaurant}
closeModal={dette.closeModal}
restauranten={dette.staten.selectedRestaurant}
/>
)
}
</div>
);
}
}
eksport-standard-App

Vi oppretter du først noen innledende staten til å holde restauranter array at vi vil være henting fra vår API. Vi lager også Booleans til å kontrollere våre UI og en selectedRestaurant objekt.

I componentDidMount, vi spørring for restauranter og oppdatere staten til å holde restauranter hentet fra API.

I createRestaurant og createReview, sender vi mutasjoner til API. Legg også merke til at vi gir et optimistisk update ved å oppdatere staten umiddelbart, slik at BRUKERGRENSESNITTET blir oppdatert før svaret kommer tilbake for å gjøre vår UI irritabel.

Neste, vi vil lage Restauranter komponent (src/Restaurants.js).

// src/Restaurants.js

import Reagere, { Komponent } fra “reagerer’;
import { css } fra ‘glamour’

klasse Restauranter strekker seg Komponent {
render() {
const { restauranter, viewReviews } = dette.rekvisitter
retur (
<div {…css-stiler.container)}>
{
restauranter.lengde === Number(0) && (
<h1
{…css-stiler.h1)}
>Opprett din første restauranten ved å klikke på +</h1>
)
}
{
restauranter.kart((r, i) => (
<div key={i}>
<img
src={r.foto}
{…css-stiler.bilde)}
/>
<p {…css-stiler.tittelen)}>{r.name}</p>
<p {…css-stiler.undertittel)}>{r.by}</p>
<p
onClick={() => viewReviews(r)}
{…css-stiler.viewReviews)}
>Vis Anmeldelser</p>
<p
onClick={() => dette.rekvisitter.showCreateReview(r)}
{…css-stiler.createReview)}
>Opprett Omtale</p>
</div>
))
}
</div>
);
}
}

eksport standard Restauranter

Denne komponenten er hovedvinduet i programmet. Vi kart over listen av restauranter og vise restaurant bilde, navn og beliggenhet, og lenker som vil åpne overlegg for å vis anmeldelser og opprette en ny gjennomgang.

Deretter vil vi se på Anmeldelser komponent (src/Reviews.js). I denne komponenten, kan vi kart over listen med anmeldelser for den valgte restaurant.

// src/Reviews.js

import Reagere fra “reagerer’
import { css } fra ‘glamour’

klasse Anmeldelser strekker seg til å Reagere.Komponent {
render() {
const { closeModal, restaurant } = dette.rekvisitter
retur (
<div {…css-stiler.overlegg)}>
<div {…css-stiler.container)}>
<h1>{restaurant.name}</h1>
{
restaurant.anmeldelser.elementer.kart((r, i) => (
<div {…css-stiler.anmeldelse)} key={i}>
<p {…css-stiler.teksten)}>{r.tekst}</p>
<p {…css-stiler.rating)}>Stjerner: {r.vurdering}</p>
</div>
))
}
<p onClick={closeModal}>Lukk</p>
</div>
</div>
)
}
}

eksport standard Anmeldelser

Neste, vil vi ta en titt på CreateRestaurant komponent (src/CreateRestaurant.js). Denne komponenten har en form som holder tritt med den form staten. Den createRestaurant klasse metoden vil kalle dette.rekvisitter.createRestaurant, passerer i form staten.

// src/CreateRestaurant.js

import Reagere fra “reagerer’
import { css } fra ‘glamour’;

klasse CreateRestaurant strekker seg til å Reagere.Komponent {
tilstand = {
navn: “, byen: “, foto:”
}
createRestaurant = () => {
hvis (
dette.staten.city === ” || denne.staten.navnet === ” || denne.staten.bilde ===”
) avkastning
dette.rekvisitter.createRestaurant(denne.staten)
dette.rekvisitter.closeModal()
}
onChange = ({ target }) => {
dette.setState({ [mål.navn]: målet.value })
}
render() {
const { closeModal } = dette.rekvisitter
retur (
<div {…css-stiler.overlegg)}>
<div {…css-stiler.form)}>
<input
plassholder= “Restaurant navn’
{…css-stiler.inngang)}
name= “navn”
onChange={dette.onChange}
/>
<input
plassholder=’Byen’
{…css-stiler.inngang)}
name=’byen’
onChange={dette.onChange}
/>
<input
plassholder=’Bilde’
{…css-stiler.inngang)}
name= “foto”
onChange={dette.onChange}
/>
<div
onClick={dette.createRestaurant}
{…css-stiler.knappen)}
>
<p
{…css-stiler.buttonText)}
>Send</p>
</div>
<div
{…css([stiler.knappen, { backgroundColor: ‘#555’}])}
onClick={closeModal}
>
<p
{…css-stiler.buttonText)}
>Avbryt</p>
</div>
</div>
</div>
)
}
}

eksport standard CreateRestaurant

Neste, vil vi ta en titt på CreateReview komponent (src/CreateReview.js). Denne komponenten har en form som holder tritt med den form staten. Den createReview klasse metoden vil kalle dette.rekvisitter.createReview, passerer i restaurant-ID og form staten.

// src/CreateReview.js

import Reagere fra “reagerer’
import { css } fra ‘glamour’;
const stjerner = [1, 2, 3, 4, 5]
klasse CreateReview strekker seg til å Reagere.Komponent {
tilstand = {
anmeldelse: “, selectedIndex: null
}
onChange = ({ target }) => {
dette.setState({ [mål.navn]: målet.value })
}
createReview = asynkron() => {
const { restaurant } = dette.rekvisitter
const input = {
tekst: dette.staten.gjennomgang,
rating: på dette.staten.selectedIndex + 1,
reviewRestaurantId: restaurant.id
}
try {
dette.rekvisitter.createReview(restaurant.id, inngang)
dette.rekvisitter.closeModal()
} catch(err) {
– konsollen.logg(‘feil under oppretting av restaurant: ‘, err)
}
}
render() {
const { selectedIndex } = dette.staten
const { closeModal } = dette.rekvisitter
retur (
<div {…css-stiler.overlegg)}>
<div {…css-stiler.form)}>
<div {…css-stiler.stjerner)}>
{
stjerner.kart((s, i) => (
<p
key={i}
onClick={() => dette.setState({ selectedIndex: i })}
{…css([stiler.- stjerners, selectedIndex === i && { backgroundColor: ‘gull’ }])}
>{s} stjerners</p>
))
}
</div>
<input
plassholder= “Anmeldelse”
{…css-stiler.inngang)}
name= “anmeldelse”
onChange={dette.onChange}
/>
<div
onClick={dette.createReview}
{…css-stiler.knappen)}
>
<p
{…css-stiler.buttonText)}
>Send</p>
</div>
<div
{…css([stiler.knappen, { backgroundColor: ‘#555’}])}
onClick={closeModal}
>
<p
{…css-stiler.buttonText)}
>Avbryt</p>
</div>
</div>
</div>
)
}
}

eksport standard CreateReview

Kjører app

Nå som vi har bygget vår back-end, konfigurert en app, og laget vårt komponenter, vi er klar til å teste det ut:

npm start

Nå, gå til http://localhost:3000. Gratulerer, du har nettopp bygget en full stack serverless GraphQL programmet!

Konklusjon

Det neste logiske steget for mange anvendelser er å gjelde flere sikkerhetsfunksjoner, som autentisering, autorisasjon og finkornet tilgangskontroll. Alle disse tingene er bakt inn i tjenesten. For å lære mer om AWS AppSync sikkerhet, sjekk ut dokumentasjon.

Hvis du ønsker å legge til hosting og en Kontinuerlig Integrasjon/Kontinuerlig Distribusjon rørledning for appen din, sjekk ut Forsterke Konsollen.

Jeg opprettholder også et par av depoter med ekstra ressurser rundt Forsterke og AppSync: Awesome AWS Forsterke og Awesome AWS AppSync.

Hvis du ønsker å lære mer om denne filosofien med å bygge apps ved hjelp av administrerte tjenester, kan du sjekke ut mitt innlegg med tittelen “Full-stack Utvikling i den Æra av Serverless Computing.”