Former, Auth og Serverless Funksjoner på Gatsby og Netlify

0
31

Abstracting infrastruktur er i vårt DNA. Veier, skoler, vannforsyning nettverk—du får ideen. Web-utvikling er ikke noe unntak: serverless arkitekturer er et vakkert uttrykk for at dette fenomenet. Statiske sider, i særdeleshet, er å snu til dynamiske, rike opplevelser.

Håndtering statiske former, autentisering, og backend funksjoner på statisk-generert nettsteder er nå en ting. Spesielt med JAMstack pioneer plattform som er Netlify. Nylig, de annonsert støtte for AWS Lambda funksjoner på front-end-sentriske nettsteder og apper. Jeg har vært meningen å dykke inn i deres “backend” funksjoner siden.

I dag, jeg gjør akkurat det, ved hjelp av en statisk Gatsby nettstedet, Netlify Skjemaer, Identitet og funksjoner. Denne veiledningen vil vise deg hvordan:

  • Legg statiske former for ditt nettsted
  • Legg til brukergodkjenning for passord-beskyttet innhold
  • Opprette en AWS Lambda-funksjon

Klar til å supercharge en statisk side med serverless funksjoner?

Vurdere å sjekke ut Netlify er Reagere-drevet statisk CMS etter dette innlegget! Og her er en tutorial på en hel kommentar arbeidsflyt, komplett med en godkjenning system, ved hjelp av JAMstack.

Statisk nettsted former, auth, og AWS Lambda-funksjoner

Før dykking i koden, la oss detalj i vår bruk tilfelle. Jeg vil være ved hjelp av tre ulike Netlify serverless funksjoner:

1. Identitet

Identitet vil bli brukt til å opprette et passord-beskyttet, avgrenset innhold-delen på Gatsby nettstedet. Godkjenning uten en backend har lenge vært en smerte på statiske nettsteder. Men denne ryddig funksjonen løser det elegant, slik at utviklere å:

Administrere registreringer, brukernavn, passord utvinning, og mer — alt uten å rulle din egen godkjenning service.

2. Former

Skjemaene vil bli brukt til å aktivere brukeren-innsendt produkt anmeldelser på området. Dynamiske skjemaer kan ta mange former (se hva jeg gjorde der?), fra enkle kontaktskjema for å kommentere, kvotering, og vurdere systemer koblet til interne verktøy.

Det er en mengde løsninger for å håndtere interaktive skjemaer på statiske nettsteder. Men med Former du kan håndtere dem direkte i din bygning og hosting service (Netlify kjerne tilbyr). Ingen behov for spam felle mailto: koblinger, konfigurere din egen server, sette opp serverless funksjoner, eller integrere tredjeparter som Formspree eller FormKeep.

Ingen JavaScript-kode, Api-er eller backend som trengs: bare en enkel HTML-skjema som er merket med netlify HTML-attributtet.

3. Funksjoner

Funksjoner vil bli brukt til å sette opp et anmeldelser moderering arbeidsflyt direkte i Slakk. Under denne funksjonen er panseret er AWS Lambda funksjoner—event-utløst, skalerbar backend-koden kan du kjøre uten din egen server. Distribusjon av disse med Netlify er like enkelt som å legge en fil til et Git-repo.

Lambda funksjoner er faktisk kraftig, men de vanligvis krever en AWS-konto og API-gateway configuration. Som med Former, Funksjoner forenkle livet ditt ved lossing legwork for å Netlify:

Din funksjonene er versjon-kontrollert, bygget, og distribueres sammen med resten av Netlify site, og Netlify API gateway automatisk håndterer service discovery. Plus, funksjoner dra nytte av kraften av Distribuere Forhåndsvisninger og tilbakerulling.

I et nøtteskall, Funksjoner tillate deg å forbedre nettstedet interaktivitet + bridge front-og backend å la dataflyt mellom tjenester.

Serverless Gatsby på Netlify: auth, statiske former, og Lambda-funksjoner

Jeg vil jumpstart denne opplæringen ved hjelp av en nedstrippet versjon av en tidligere Gatsby siden vi bygget.

Å lære Gatsby grunnleggende, sjekk ut den offisielle opplæringen. Vi har også to e-handel opplæring med Gatsby her og her.

Forutsetninger

For denne opplæringen, vil du trenger:

  • En gratis konto Netlify
  • Netlify Former Pro for Slakk integrering (valgfritt—betalt funksjon)

1. Gaffel den Gatsby prosjektet

Start med gaffel repo:

Se på GitHub

Jeg foreslår å spille rundt med det å bli kjent med prosjektet. Produktene er i src/data/produkter—mappe med alle inne i Markdown-filer. Disse filene er lastet inn under bygge gang og brukes til å injisere riktig info på våre maler. Dette er gjort innenfor gatsby-node.js fil.

2. Legge til Identitet for godkjenning

Hvis du åpnet hvilket som helst produkt-fil, vil du sannsynligvis så det er et felt vi ikke vanligvis bruker i Snipcart demoer: et eget attributt. Målet er enkelt: å vise disse “eksklusiv” produkter bare når en bruker er logget på.

For å håndtere det, jeg brukte Netlify Identitet widget, en enkel måte å legge til godkjenning til en statisk nettside.

Du kan installere Identitet-pakken ved å kjøre:

npm installere –spare netlify-identitet-widgeten

Sørg for å inkludere det i overskriften din! Inne i src/components/Header/index.js fil, jeg har lagt denne linjen etter h1 avsluttende koden:

<div data-netlify-identitet-meny – ></div>

Deretter kan du importere modulen på toppen av filen din med

const netlifyIdentity = krever(“netlify-identitet-widget”);

Og erklære en componentDidMount funksjon som sådan:

componentDidMount(){
netlifyIdentity.init();
}

Identiteten widget nå injiserer riktig logg inn skjemaer på innsiden som <div>. Nå som du har en statisk form for å logge inn, trenger du de riktige logikk for å validere om en bruker er logget på eller ikke.

Jeg brukte denne logikken til å vise riktig, passord-beskyttet produkter til innloggede brukere. For å gjøre dette, laget jeg en products.js inne i src/sider-mappen, og definert følgende komponenter:

import Reagere fra “reagerer’
import Link fra ‘gatsby-link’
import stiler fra ‘./produkter.modul.css’
const netlifyIdentity = krever(“netlify-identitet-widget”);

eksport standard klasse Produkter strekker seg til å Reagere.Komponent {
constructor(data){
super(data);

dette.tilstand = {
produkter: []
}
}

getProducts(){
tilbake netlifyIdentity.currentUser() != null
? dette.rekvisitter.data.allMarkdownRemark.kantene
: dette.rekvisitter.data.allMarkdownRemark.kantene
.filteret(x => !x.node.frontmatter.private)
}

updateProducts(){
dette.setState({ produkter: dette.getProducts() });
}

componentDidMount(){
netlifyIdentity.på(“logg inn”, user => dette.updateProducts());
netlifyIdentity.på(“logg ut”, () => dette.updateProducts());
dette.updateProducts();
}

render(){
retur (
<div>
<h1>Produkter</h1>
<p>for Å logge bruk e-post: geeks@snipcart.com med passord: admin</p>

<ul className={stiler.itemsList}>
{dette.staten.produkter.kart((o, index) =>
<li key={indeks} className={stiler.elementet}>
<Link={o.node.frontmatter.loc}>
<figur>
<img className={stiler.bilde} src={o.node.frontmatter.bilde} alt={o.node.frontmatter.navn}></img>
<figcaption className={stiler.figCaption}>Kjøpe {o.node.frontmatter.navn}} nå</figcaption>
</figure>
</Link>
</li>
)}
</ul>
</div>)
}
}

eksport const query = graphql`
søket allProducts {
allMarkdownRemark {
kantene {
node {
frontmatter {
sku,
loc,
pris,
desc,
privat,
navn,
bilde
}
}
}
}
`

Jeg vil ikke forklare GraphQL bit her. Hvis du er interessert, les mer her.

Viktig å forstå hva som skjer inne i componentDidMountlifecycle funksjon. Jeg er bindende meg til widget ‘logg inn’ og ‘logout’ hendelser for å oppdatere tilgjengelige produkter.

Slutt-resultatet er ganske awesome:

3. Håndtering statiske former for vurderinger

For å legge til produktanmeldelser til Gatsby nettstedet, brukte jeg Netlify Skjemaer. Du kan ta med sine Former på ditt eget nettsted ved å legge til en ” data-netlify=”true” ” (eller bare netlify) attributt til et skjema erklæring. Jeg inkluderte det i min src/components/product.js fil etter siste delen tag.

Du vil også trenge å erklære en formId variabel før retur av ditt gjengi funksjon, for eksempel:

render(){
hvis(denne.rekvisitter.data.markdownRemark.frontmatter.privat
&& !dette.staten.loggedIn){
tilbake fourOfour();
}

var formId = ” produkt-${dette.rekvisitter.data.markdownRemark.frontmatter.sku}`

const-knappen = i dette.rekvisitter.data.markdownRemark.frontmatter.privat ? (
<- knappen type=”button” className={`${stiler.buyButton}`}>
UTSOLGT
</button>
) : (
<- knappen type=”button” className={`${stiler.buyButton} snipcart-legg til-element”}
data-element-name={dette.rekvisitter.data.markdownRemark.frontmatter.name}
data-element-id={dette.rekvisitter.data.markdownRemark.frontmatter.sku}
data-element-bilde={dette.rekvisitter.data.markdownRemark.frontmatter.bilde}
data-element-url={`${NETLIFY_URL}${dette.rekvisitter.beliggenhet.banenavn}`}
data-element-pris={dette.rekvisitter.data.markdownRemark.frontmatter.pris}
data-item-description={dette.rekvisitter.data.markdownRemark.frontmatter.desc}>
Kjøp det nå for {dette.rekvisitter.data.markdownRemark.frontmatter.pris}$
</button>
);

retur (
<div>
<h1>{dette.rekvisitter.data.markdownRemark.frontmatter.name}</h1>
<div className={stiler.brødsmule-navigeringen}>
<Link til=’/’>Tilbake til produkter</Link>
</div>
<p>{dette.rekvisitter.data.markdownRemark.frontmatter.desc}</p>

<delen className=”delen__produkt”>
<figur className={stiler.productFigure}>
<img src={dette.rekvisitter.data.markdownRemark.frontmatter.bilde} />
</figure>

<artikkel>
{dette.rekvisitter.data.markdownRemark.frontmatter.beskrivelse}
</article>
<div className={stiler.handlinger}>
{knappen}
</div>
</avsnitt>
<avsnitt>
<h3 className=”anmeldelser”>Omtaler</h3>
<div className=”anmeldelser__ – listen”>
{dette.staten.anmeldelser.kart((o) =>
<p key={o.antall}>
<div className=”gjennomgang__navn”>{o.name}</div>
<div>{o.data.melding}</div>
</p>
)}
</div>

<form className=”gjennomgang__formen” navn={formId} method=”POST” data-netlify-honeypot=”bot-feltet” data-netlify=”true”>
<input type=”hidden” name=”form-navn” value={formId} />
<div className=”feltet__form”>
<label>NAVN</label>
<input type=”text” name=”navn”></input>
</div>
<div className=”feltet__form”>
<label>E-post</label>
<input type=”e-post” name=”e-post”></input>
</div>
<div className=”feltet__form”>
<label>MELDING</label>
<textarea name=”melding”></textarea>
</div>

<- knappen for className=”knappen__form” type=”submit”>SEND</button>
</form>
</avsnitt>
</div>)
}

Boom, statiske former som er på nettstedet ditt!

Imidlertid, for å vise bidrag som kommer inn via disse skjemaene, trenger du en Netlify funksjon for å hente inn og gå tilbake brukeranmeldelser. For å gjøre dette, laget jeg en netlify.toml fil med følgende innhold:

[bygge]
funksjoner = “funksjoner”

Jeg og deretter sette et funksjoner mappen direkte i rot-prosjektet. Inne i det, plasserte jeg en fetchreviews.js filen med:

const https = kreve(‘https’);

eksport.behandleren = function(hendelse, kontekst, tilbakeringing) {
var id = event.queryStringParameters.id;
var token = prosessen.konv.netlify_access_token;

if(id == undefined){
innb.(‘En produkt-id må være spesifisert.’, {
statusCode: 500
})
}

var valg = {
vertsnavn: ‘api.netlify.com’,
port: 443,
metode: ‘FÅ’,
overskrifter: {
‘Content-Type’: ‘application/json’
}
};

var queryToken = `access_token=${token}`;
var opts1 = Objekt.tilordne({}, valg, { bane: `/api/v1/sites/${prosessen.konv.site_id}/skjemaer?${queryToken}`});

var req = https.forespørsel(opts1, funksjon(res) {

res.setEncoding(‘utf8’);
var kroppen = “”;

res.på(‘data’, data => {
kroppen += data;
});

res.på(‘end’, function () {
kropp = JSON.parse(kroppen);

var form = kroppen.filteret(x => x.navnet == `produkt-${id}`)[0];
var opts2 = Objekt.tilordne({}, valg, { bane: `/api/v1/skjemaer/${form.id}/innleveringer?${queryToken}`});

var req2 = https.forespørsel(opts2, funksjon(res2) {
res2.setEncoding(‘utf8’);
var body2 = “”;

res2.på(“data”, (data) => {
body2 += data;
});

res2.på(‘end’, function () {
innb.(null, {
statusCode: 200,
overskrifter: {
“Access-Control-La-Opprinnelse” : “*”,
‘Content-Type’: ‘application/json’
},
kropp: body2
})
});
});

req2.avslutt();
});
});

req.avslutt();
}

Funksjonen sjekker om en produkt-ID ble gitt som en søkeparameter. Hvis det er en ID, og henter skjemaet med navn på produkt-{produkt-id} for å få alle anmeldelser fra det. Denne måten jeg kunne vis anmeldelser i fronten.

Jeg har lagt to funksjoner for å product.js for å gjøre dette:

constructor(props){
super(props);

dette.tilstand = {
anmeldelser: [],
loggedIn: false
}
}

componentDidMount(){
hente(`https://${NETLIFY_FUNC}/fetchreviews?id=${dette.rekvisitter.data.markdownRemark.frontmatter.sku}`)
.deretter(x => x.json())
.deretter(x => {
dette.setState({anmeldelser: x})
})

hvis(netlifyIdentity.currentUser() != null){
dette.setState({loggedIn: true});
}

netlifyIdentity.på(“logg inn”, user => dette.setState({loggedIn: true}));
netlifyIdentity.på(“logg ut”, () => dette.setState({loggedIn: false}));
}

Så, like før gjennomgå skjemaet:

{dette.staten.anmeldelser.kart((o) =>
<p key={o.antall}>{o.navn}: {o.data.melding}</p>
)}

Ovenfor, montert komponent henter nye funksjoner for å få bestemt produkt anmeldelser. Den oppdaterer også staten, og vise dem på sidene. Du kan også se at vi bestemte oss for å sette en “utsolgt” – knappen for private produkter, dette er fordi disse er private og ville ikke passere våre validering hvis vi skulle bare sette den aktuelle URL-adressen, kan vi likevel gjør det, men det ville kreve litt mer arbeid ut av omfanget av denne demoen.

Hvis du ønsker å teste dine funksjoner uten å deployere til Netlify, bruk netlify-lambda-node-pakke til å gjøre dette lokalt. Når du har installert det (npm installere netlify-lambda) kjøre netlify-lambda tjene ./ i prosjektet mappen. Funksjonen vil kjøre på http://localhost:9000/fetchreviews.

Du kan oppdatere hente ruten ovenfor og få den samme atferden du vil ha med en vertsbasert funksjon.

4. Konfigurere en AWS Lambda funksjon med Slakk

Du må Netlify Former Pro for å utløse en funksjon på formen bidrag.

Sist, men ikke minst: den anmeldelser moderering arbeidsflyt direkte i Slakk. Målet er enkelt: trykk anmeldelse informasjon og varsling til Slakk, og la det enten *beholde* eller *avvis* gjennomgang fra Slakk.

For å gjøre dette, så jeg laget 2 nye funksjonene i funksjoner mappe: notifyslack.js og answerslack.js. Den første er varslet av Netlify er webhook av hvert skjema innsending og er ansvarlig for å kommunisere dette til å Stille med nødvendige tiltak elementer. Jeg laget en liten Slakk app for at dette skal fungere (referanse).

Her er de tillatelser appen behov:

Interaktive komponenter config:

Forespørsel URL – feltet er der Netlify funksjonen kan kalles.

Med disse satt opp, jeg installerte appen min og åpnet den Innkommende webhooks kategorien. Jeg kopierte webhook URL, og kom tilbake til mitt prosjekt.

Inne i funksjoner, opprettet jeg notifyslack.js filen med:

var https = krever(“https”);

eksport.behandleren = function(hendelse, kontekst, tilbakeringing) {
var kroppen = JSON.parse(event.kroppen);

if(kropp != null && kropp.data != null){
var data = kroppen.data;

var message = `Ny gjennomgang fra ${data.e-post} n ${data.navn}: ${data.melding}`;
var attach = [
{
“title”: “Gjennomgå ID”,
“tekst”: kropp.id
},
{
“title”: “ønsker du å holde gjennomgang?”,
“tekst”: melding,
“fallback”: “Du kan ikke iverksette tiltak for denne gjennomgangen.”,
“callback_id”: “answer_netlify”,
“color”: “#3AA3E3”,
“attachment_type”: “standard”,
“tiltak”: [
{
“name”: “svar”,
“text”: “Hold”,
“type”: “button”,
“value”: “holde”
},
{
“name”: “svar”,
“text”: “Avvis”,
“type”: “button”,
“stil”: “fare”,
“value”: “avvis”,
“bekrefte”: {
“title”: “Er du sikker?”,
“text”: “Når det er gjort anmeldelsen vil bli slettet”,
“ok_text”: “Ja”,
“dismiss_text”: “Nei”
}
}
]
}
]

var postData = JSON.stringify({
vedlegg: fest
});

var valg = {
vertsnavn: ‘hooks.slack.com’,
port: 443,
bane: prosessen.konv.slack_webhook_url,
metode: ‘POST’,
overskrifter: {
‘Content-Type’: ‘application/json’
}
};

var req = https.forespørsel(valg, funksjon(res) {

res.setEncoding(‘utf8’);

res.på(‘end’, function () {
innb.(null, {
statusCode: 200
})
});
});

req.på(‘feil’, function (e) {
– konsollen.logg(‘Problem med forespørsel:’, e.melding);
});

req.skrive(postData);
req.avslutt();

innb.(null, {
statusCode: 200
})
}
}

Her må du oppdatere banen verdi av opsjoner objekt med tilsvarende Slakk app webhook URL.

I øyeblikket, dette vil bare varsle Slakk—uansett hvilken handling du valgte, ville ikke utløse noe annet.

For å gjøre Slakk varsling interaktive, laget jeg en 3. funksjon inne i en fil som heter answerslack.js. Denne funksjonen er trolig den mest kompliserte, men det er for det meste forespørsler overhead, så bær over med meg:

var https = krever(“https”);
var qs = kreve(‘querystring’)

funksjonen getURL(href) {
var match = href.match(/^(https?:)//(([^:/?#]*)(?::([0-9]+))?)([/]{0,1}[^?#]*)(?[^#]*|)(#.*|)$/);
tilbake match && {
href: href,
protokoll: match[1],
vert: match[2],
hostname: match[3],
port: match[4],
banenavn: match[5],
søk: match[6],
hash: match[7]
}
}

eksport.behandleren = function(hendelse, kontekst, tilbakeringing) {
var json = JSON.parse(qs.parse(event.kroppen).nyttelast);

var svar = json.handlinger[0].verdi;
var access_token = prosessen.konv.netlify_access_token;
var id = json.original_message.vedlegg[0].tekst;

if(svar == ‘avvise’){
var valg = {
vertsnavn: ‘api.netlify.com’,
port: 443,
bane: `/api/v1/bidrag/${id}?access_token=${access_token}`,
metode: ‘SLETT’,
overskrifter: {
‘Content-Type’: ‘application/json’
}
};

var req1 = https.forespørsel(valg, funksjon(res) {

res.setEncoding(‘utf8’);

res.på(‘end’, function () {
– konsollen.logg(`Gjennomgang med-id: ${id} ble slettet.`)
});
});

req1.på(‘feil’, function (e) {
– konsollen.logg(‘Problem med forespørsel:’, e.melding);
});

req1.avslutt();
}

var postData = JSON.stringify({
replace_original: true,
vedlegg: [{
tekst: svar == ‘holde’
? `Gjennomgang (${id}) ble godkjent!`
: `Gjennomgang (${id}) ble avvist.`
}]
});

var url = getURL(json.response_url);

var valg = {
vertsnavn: url.vertsnavn,
bane: url.banenavn,
metode: ‘POST’,
overskrifter: {
‘Content-Type’: ‘application/json’
}
};

var req = https.forespørsel(valg, funksjon(res) {

res.setEncoding(‘utf8’);

res.på(‘end’, function () {
innb.(null, {
statusCode: 200
})
});
});

req.på(‘feil’, function (e) {
– konsollen.logg(‘Problem med forespørsel:’, e.melding);
});

req.skrive(postData);
req.avslutt();

innb.(null, {
statusCode: 200
})
}

Jeg analysere hendelsen nyttelast og sjekk om handlingen verdi var avvise. Hvis det ikke er, det er nødvendigvis holde—ingenting å gjøre. Men hvis det er det, jeg må ringe Netlify API for å slette den avviste anmeldelsen. Jeg hente gjennomgå ID sette tidligere inne i det første vedlegget tekst med følgende linje:

json.original_message.vedlegg[0].tekst;

Når dette er gjort, kan jeg slette det med en API-kall. Jeg så gi våre Slakk brukere tilbakemelding ved å ringe svar URL.

Jeg er slags stolt av det endelige arbeidsflyt her TBH:

5. Distribuere Gatsby nettstedet på Netlify

Her, jeg presset alt til GitHub, og koblet den opp til Netlify bruke disse innstillingene:

Du kan se har vi brukt noen av miljøvariabler med prosessen.konv.{variabel} notasjon i demoen.

Disse er private innstillinger ønsker vi ikke å gjøre offentlig. For å definere din direkte, gå til /innstillinger/distribuerer i Netlify dashboard, traff Redigere variabler, og legg inn følgende:

  • netlify_access_token: token opprettet tidligere inne netlify
  • site_id: nettadressen for nettstedet uten protokollen
  • slack_webhook_url: Din Slakk app webhook URL

Nettstedet deployert, tid til å leke seg!

Les dette for å lære hvordan du kan implementere en plass på Netlify.

Live demo og GitHub repo