Vormen, Auth en Serverloze Functies op Gatsby en Netlify

0
16

Abstraheer infrastructuur zit in ons DNA. Wegen, scholen, water, netwerken—je krijgt het idee. Ontwikkeling van het Web is geen uitzondering: serverloze architecturen zijn een prachtige uiting van dat fenomeen. Statische sites, in het bijzonder, draaien in een dynamische, rijke ervaringen.

Behandeling statische formulieren, verificatie, en de backend functies op statisch-generated sites is nu een ding. Vooral met de JAMstack pioneer-platform, dat is Netlify. Recentelijk is aangekondigd ondersteuning van AWS Lambda functies aan de front-end-centric sites en apps. Ik heb zin om te duiken in hun “backend” heeft aangezien.

Vandaag ben ik precies dat te doen, met behulp van een statische Gatsby site, Netlify de Vormen, de Identiteit en de Functies heeft. Deze tutorial zal u tonen hoe u:

  • Het toevoegen van statische formulieren aan uw site
  • Toevoegen gebruiker authenticatie om wachtwoord-beveiligde inhoud
  • Het maken van een AWS Lambda functie

Klaar voor een boost van een statische site met serverloze functies?

Overwegen het controleren van Netlify ‘ s Reageren-aangedreven statische CMS na deze post! En hier is een tutorial op een hele reactie workflow, compleet met een goedkeuring systeem, met behulp van de JAMstack.

Statische site vormen, auth en AWS Lambda-functies

Voor het duiken in de code, laat detail onze use case. Ik gebruik drie verschillende Netlify serverloze kenmerken:

1. Identiteit

Identiteit zal worden gebruikt voor het maken van een wachtwoord beveiligde, afgeschermde inhoud sectie op de Gatsby site. Verificatie zonder een backend is al lang een pijn op statische sites. Maar deze handige functie lost dit elegant, waardoor ontwikkelaars:

Beheren aanmeldingen, aanmeldingen, de terugwinning van het wachtwoord, en meer — allemaal zonder het rollend uw eigen authenticatie service.

2. Vormen

Formulieren zullen worden gebruikt om de gebruiker verstrekte reviews op de site. Dynamische vormen kan vele vormen aannemen (zie wat ik daar deed?), van eenvoudig contactformulier tot het maken van opmerkingen, het maken van offertes, en het review-systemen aangesloten op interne tools.

Er is een overvloed aan oplossingen te hanteren interactieve formulieren op statische sites. Maar met Formulieren die u kunt verwerken ze direct binnen uw gebouw en de hosting-service (Netlify het basisaanbod). Geen noodzaak voor spam-trap op mailto: – links, het configureren van uw eigen server, het opzetten van een server is niet vereist functies, of het integreren van derde partijen, zoals Formspree of FormKeep.

Geen JavaScript, Api ‘ s, of backend nodig: gewoon een eenvoudige HTML-formulier gelabeld met de netlify HTML-attribuut.

3. Functies

Functies worden gebruikt om een beoordelingen moderatie workflow rechtstreeks in Speling. Onder deze functie is capuchon AWS Lambda-functies—bij-gebeurtenis, schaalbare backend code die u kunt uitvoeren zonder uw eigen server. De implementatie van deze met Netlify is zo eenvoudig als het toevoegen van een bestand naar een Git repo.

Lambda functies zijn inderdaad krachtig, maar ze normaal gesproken moet een AWS account en API gateway-configuratie. Zoals met Formulieren, Functies vereenvoudig je leven door het ontlasten van de informatieverzameling te Netlify:

Uw functies zijn onder versiebeheer, gebouwd en geïmplementeerd samen met de rest van uw Netlify site, en de Netlify API gateway automatisch verwerkt service discovery. Plus, uw functies profiteren van de kracht van het Implementeren van Previews en herstelfuncties.

In een notendop, de Functies kunt u de site interactiviteit + brug de front-en backend te laten gegevensstroom tussen de diensten.

Serverloze Gatsby op Netlify: auth, statische vormen, en Lambda-functies

Ik zal jumpstart deze tutorial met behulp van een uitgeklede versie van een eerdere Gatsby website die we gebouwd.

Om te leren Gatsby basics, check out de officiële leerprogramma. We hebben ook twee e-commerce tutorials met Gatsby hier en hier.

Voorwaarden

Voor deze tutorial heb je nodig:

  • Een gratis account Netlify
  • Netlify Vormen Pro voor de Slack integratie (optioneel betaalde functie)

1. Forking de Gatsby project

Begin met het forken van de repo:

Bekijk op GitHub

Ik stel voor het spelen rond met het om vertrouwd te raken met het project. De producten zijn in de src/data/producten-map—alle in Markdown-bestanden. Deze bestanden worden geladen tijdens het bouwen van de tijd en gebruikt voor het injecteren van de juiste info in onze sjablonen. Dit is gedaan in de gatsby-node.js -bestand.

2. Het toevoegen van Identiteit voor verificatie

Als u geopend enig product bestand, je zag waarschijnlijk is er een veld we meestal niet gebruiken in Snipcart demo ‘ s: een eigen kenmerk. Het doel is simpel: laten zien dat deze “exclusieve” producten alleen wanneer een gebruiker is ingelogd.

Aan het verwerken, ik gebruikte Netlify de Identiteit van een widget, een eenvoudige manier van het toevoegen van verificatie van een statische website.

U kunt het installeren van de Identiteit pakket met:

npm install –opslaan netlify-identiteit-widget

Zorg ervoor dat het in je kop! Binnen de src/components/Header/index.js bestand, voegde ik deze lijn na de h1 afsluitende tag:

<div data-netlify-identiteit-menu></div>

U kunt vervolgens te importeren in de widget op de top van uw bestand met

const netlifyIdentity = require(“netlify-identiteit-widget”);

En het declareren van een componentDidMount functie als zodanig:

componentDidMount(){
netlifyIdentity.init();
}

De Identiteit widget nu injecteert de juiste login vormen binnen de <div>. Nu dat u een statisch formulier om in te loggen, moet u de juiste logica te valideren als een gebruiker is ingelogd of niet.

Ik gebruikte deze logica om de juiste toon, met een wachtwoord beschermde producten aan ingelogde gebruikers. Om dit te doen, heb ik een products.js in de src/pagina ‘ s map en gedefinieerd op het volgende onderdeel:

importeren Reageren van ‘reageren’
Koppeling importeren van ‘gatsby-link’
import styles ‘./producten.de module.css’
const netlifyIdentity = require(“netlify-identiteit-widget”);

export standaard klasse Producten breidt Reageren.Onderdeel {
constructor(data){
super(data);

deze.staat = {
producten: []
}
}

getProducts(){
terug netlifyIdentity.huidigegebruiker() != null
? deze.props.de gegevens.allMarkdownRemark.randen
: dit.props.de gegevens.allMarkdownRemark.randen
.filter(x => !x.knooppunt.frontmatter.privé -)
}

updateProducts(){
deze.setState({ producten: dit.getProducts() });
}

componentDidMount(){
netlifyIdentity.op(“login”, user => dit.updateProducts());
netlifyIdentity.op(“logout” (afmelden), () = > dit.updateProducts());
deze.updateProducts();
}

render(){
return (
<div>
<h1>Producten</h1>
<p>om in Te loggen gebruik maken van de e-mail: geeks@snipcart.com met wachtwoord: admin</p>

<ul className={stijlen.itemsList}>
{dit.staat.producten.kaart((o, index) =>
<li key={index} className={stijlen.item}>
<Link={o.knooppunt.frontmatter.loc}>
<afbeelding>
<img className={stijlen.afbeelding} src={o.knooppunt.frontmatter.afbeelding} alt={o.knooppunt.frontmatter.naam}></img>
<figcaption className={stijlen.figCaption}>Koop de {o.knooppunt.frontmatter.naam}</figcaption>
</figure>
</Link>
</li>
)}
</ul>
</div>)
}
}

export const query = graphql`
query allProducts {
allMarkdownRemark {
randen {
node {
frontmatter {
sku,
loc,
prijs
desc,
privé,
naam,
afbeelding
}
}
}
}
`

Ik ga niet uitleggen de GraphQL beetje hier. Als je geïnteresseerd bent, lees hier meer.

Het is belangrijk om te begrijpen wat er gebeurt binnen de componentDidMountlifecycle functie. Ik ben bindend mezelf voor de widget ‘aanmelden’ en ‘afmelden’ gebeurtenissen update van de beschikbare producten.

Het eind-resultaat is pretty awesome:

3. Behandeling statische formulieren beoordelingen

Voor het toevoegen van het product beoordelingen voor de Gatsby site, ik gebruikte Netlify ‘ s Vormen. U kunt hun Formulieren op uw eigen website door het toevoegen van een ‘data-netlify=”true”‘ (of netlify) attribuut van een formulier verklaring. Ik het in mijn src/components/product.js bestand na de laatste paragraaf-tag.

Je moet ook verklaren van een formId variabele vóór de terugkeer van uw render-functie, zoals:

render(){
als dit.props.de gegevens.markdownRemark.frontmatter.privé
&& !deze.staat.loggedIn){
terug fourOfour();
}

var formId = ” product-${dit.props.de gegevens.markdownRemark.frontmatter.sku}`

const-toets =.props.de gegevens.markdownRemark.frontmatter.privé ? (
<button type=”button” className={`${stijlen.buyButton}`}>
UITVERKOCHT
</button>
) : (
<button type=”button” className={`${stijlen.buyButton} snipcart-add-item`}
data-item-naam={dit.props.de gegevens.markdownRemark.frontmatter.naam}
data-item-id={dit.props.de gegevens.markdownRemark.frontmatter.sku}
data-post-image={dit.props.de gegevens.markdownRemark.frontmatter.afbeelding}
data-item-url={`${NETLIFY_URL}${dit.props.ligging.padnaam}`}
data-item-prijs={dit.props.de gegevens.markdownRemark.frontmatter.prijs}
data-item-description={dit.props.de gegevens.markdownRemark.frontmatter.desc}>
Nu kopen, nu kopen voor {dit.props.de gegevens.markdownRemark.frontmatter.prijs}$
</button>
);

return (
<div>
<h1>{dit.props.de gegevens.markdownRemark.frontmatter.naam}</h1>
<div className={stijlen.breadcrumb}>
<Link=’/’>Terug naar de producten</Link>
</div>
<p>{dit.props.de gegevens.markdownRemark.frontmatter.desc}</p>

de sectie <sectie className=”section__product”>
<figuur className={stijlen.productFigure}>
<img src={dit.props.de gegevens.markdownRemark.frontmatter.afbeelding} />
</figure>

<artikel>
{dit.props.de gegevens.markdownRemark.frontmatter.beschrijving}
</article>
<div className={stijlen.acties}>
{knop}
</div>
</section>
de sectie <sectie>
<h3 className=”reviews”>Recensies</h3>
<div className=”reviews__list”>
{dit.staat.beoordelingen.kaart (o) =>
<p key={o.aantal}>
<div className=”review__naam”>{o.naam}</div>
<div>{o.de gegevens.bericht}</div>
</p>
)}
</div>

<form className=”review__vorm” naam={formId} method=”POST” data-netlify-honeypot=”bot-veld” data-netlify=”true”>
<input type=”hidden” name=”form-naam” value={formId} />
<div className=”field__formulier”>
<label>NAAM</label>
<input type=”text” name=”naam”></input>
</div>
<div className=”field__formulier”>
<label>e-MAIL</label>
<input type=”email” name=”email”></input>
</div>
<div className=”field__formulier”>
<label>BERICHT</label>
<textarea name=”bericht”></textarea>
</div>

knop <className=”knop__formulier” type=”submit”>VERZENDEN</button>
</form>
</section>
</div>)
}

Boom, statische formulieren op uw site!

Echter, om te laten zien inzendingen die via deze formulieren, moet u een Netlify functie op te halen en terug ervaringen. Om dit te doen, heb ik een netlify.toml bestand met de volgende inhoud:

[bouwen]
functies = “functies”

Ik zet dan een functies map in de hoofdmap project. Binnen, plaatste ik een fetchreviews.js bestand met:

const https = (‘https’);

de export.handler = function(event, de context, de callback) {
var id = gebeurtenis.queryStringParameters.id;
var-token = proces.env.netlify_access_token;

if(id == undefined){
callback(‘product-id moet worden opgegeven.’, {
statusCode: 500
})
}

var options = {
hostnaam: ‘api.netlify.com’,
poort: 443,
methode: ‘VOOR’,
headers: {
‘Content-Type’: ‘application/json’
}
};

var queryToken = `access_token=${token}`;
var opts1 = Object.toewijzen({}, opties, { baan: `/api/v1/sites/${proces.env.site_id}/formulieren?${queryToken}`});

var req = https.verzoek(opts1, functie(res) {

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

res.op(‘data’, data => {
body += data;
});

res.op(‘end’, function () {
lichaam = JSON.parse(het lichaam);

var-vorm = body.filter(x => x.naam == `product-${id}`)[0];
var opts2 = Object.toewijzen({}, opties, { baan: `/api/v1/formulieren/${formulier.id}/inzendingen?${queryToken}`});

var req2 = https.verzoek(opts2, functie(res2) {
res2.setEncoding(‘utf8’);
var body2 = “”;

res2.op(“gegevens”, (data) => {
body2 += data;
});

res2.op(‘end’, function () {
callback(null, {
statusCode: 200,
headers: {
“Access-Control-Allow-Origin” : “*”,
‘Content-Type’: ‘application/json’
},
lichaam: body2
})
});
});

req2.end();
});
});

req.end();
}

De functie controleert of een product-ID werd gezien als een query parameter. Als er sprake is van een ID, het haalt het formulier met de naam van het product-{product id} om alle beoordelingen. Op deze manier kon ik toon reviews in het front-end.

Ik voegde twee functies product.js om dit te doen:

constructor(rekwisieten){
super(rekwisieten);

deze.staat = {
beoordelingen: [],
loggedIn: false
}
}

componentDidMount(){
ophalen(`https://${NETLIFY_FUNC}/fetchreviews?id=${dit.props.de gegevens.markdownRemark.frontmatter.sku}`)
.dan is(x => x.json())
.dan is(x => {
deze.setState({beoordelingen: x})
})

als(netlifyIdentity.huidigegebruiker() != null){
deze.setState({loggedIn: true});
}

netlifyIdentity.op(“login”, user => dit.setState({loggedIn: true}));
netlifyIdentity.op(“logout” (afmelden), () = > dit.setState({loggedIn: false}));
}

Dan, net vóór het review formulier:

{dit.staat.beoordelingen.kaart (o) =>
<p key={o.aantal}>{o.naam}: {o.de gegevens.bericht}</p>
)}

Boven, de gemonteerde component haalt de nieuwe functies te krijgen specifieke product reviews. Het werkt ook de staat, en deze weergeven op de pagina ‘ s. U kunt ook zien dat we besloten om een “Verkocht” button voor de eigen producten, want deze zijn privé en niet langs ons validatie als we gewoon de huidige URL, dat we nog kunnen doen, maar het vereist een beetje meer werk buiten de scope van deze demo.

Als u wilt testen of uw functies zonder het inzetten van te Netlify, gebruik de netlify-lambda knooppunt pakket te doen op lokaal niveau. Als je eenmaal hebt geïnstalleerd (npm installeren netlify-lambda) uitvoeren netlify-lambda dienen ./ in je project map. De functie wordt uitgevoerd op http://localhost:9000/fetchreviews.

U kunt een update ophalen route boven en krijg hetzelfde gedrag dat je zou hebben met een hosted functie.

4. Het configureren van een AWS Lambda functie met Speling

U moet Netlify Vormen Pro, om te leiden tot een functie op vorm inzendingen.

Laatste maar niet de minste: de beoordelingen moderatie workflow rechtstreeks in Speling. Het doel is eenvoudig: druk review details en aanmelding voor de Verslapte en laten ** of *weigeren* review van Slack.

Om dit te doen, heb ik 2 nieuwe functies in de functies map: notifyslack.js en answerslack.js. De eerste kennisgeving door Netlify de webhook van elke verzending van het formulier en is verantwoordelijk om deze te Slap is met de juiste actie-items. Ik heb een kleine Speling app voor dit werk (referentie).

Hier zijn de machtigingen de app heeft:

Interactieve onderdelen config:

De Aanvraag-URL – veld is, waar je Netlify functie kan worden genoemd.

Met deze set-up, ik heb geïnstalleerd in mijn app en opende de Inkomende webhooks tabblad. Ik gekopieerd van de webhook URL, en weer terug naar mijn project.

Binnen functies, heb ik de notifyslack.js bestand met:

var https = (‘https’);

de export.handler = function(event, de context, de callback) {
var body = JSON.parse(evenement.het lichaam);

als(lichaam != null && lichaam.gegevens != null){
var data = lichaam.gegevens;

var bericht = `Nieuwe review van ${gegevens.e-mail} n ${gegevens.naam}: ${gegevens.bericht}`;
var hechten = [
{
“titel”: “ID”,
“tekst”: lichaam.id
},
{
“titel”: “wil je het controleren?’,
“tekst”: bericht
“fallback”: “Je kunt niet van het nemen van acties voor deze review.”,
“callback_id”: “answer_netlify”,
“color”: “#3AA3E3”,
“attachment_type”: “standaard”,
“acties”: [
{
“naam”: “respons”,
“text”:””,
“type”: “knop”,
“value”: “houden”
},
{
“naam”: “respons”,
“text”: “Weigeren”,
“type”: “knop”,
“style”: “gevaar”,
“value”: “weigeren”,
“bevestig”: {
“titel”: “Bent u zeker?”,
“text”: “Zodra het klaar is zal de evaluatie worden verwijderd’,
“ok_text”: “Ja”,
“dismiss_text”: “Geen”
}
}
]
}
]

var postData = JSON.stringify({
bijlagen: bevestig
});

var options = {
hostnaam: ‘hooks.slack.com’,
poort: 443,
pad: proces.env.slack_webhook_url,
methode: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’
}
};

var req = https.verzoek(opties functie(res) {

res.setEncoding(‘utf8’);

res.op(‘end’, function () {
callback(null, {
statusCode: 200
})
});
});

req.op(‘error’, function (e) {
console.log(‘Probleem met een verzoek:”, e.bericht);
});

req.schrijven(postData);
req.end();

callback(null, {
statusCode: 200
})
}
}

Hier moet je het pad bijwerken waarde van de opties object met de bijbehorende Slack app webhook URL.

Op het moment, dit zou enkel op de hoogte Slack—ongeacht de door u gekozen actie zou niet leiden tot iets anders.

Om de Speling kennisgeving interactieve, ik heb een 3e functie in een bestand met de naam answerslack.js. Deze functie is waarschijnlijk de meest ingewikkelde, maar het is voornamelijk verzoeken overhead, dus geduld met mij:

var https = (‘https’);
var qs = (‘querystring’)

functie getURL(href) {
var match = href.match(/^(https?:)//(([^:/?#]*)(?::([0-9]+))?)([/]{0,1}[^?#]*)(?[^#]*|)(#.*|)$/);
terug match && {
href: href,
protocol: [1],
host: [2],
hostname: [3],
poort: [4],
padnaam: match[5],
zoeken: [6],
hash: [7]
}
}

de export.handler = function(event, de context, de callback) {
var json = JSON.parse(qs.parse(evenement.lichaam).laadvermogen);

var answer = json.acties[0].waarde;
var access_token = proces.env.netlify_access_token;
var id = json.original_message.bijlagen[0].tekst;

if(antwoord == ‘weigeren’){
var options = {
hostnaam: ‘api.netlify.com’,
poort: 443,
pad: `/api/v1/inzendingen/${id}?access_token=${access_token}`,
methode: ‘VERWIJDEREN’,
headers: {
‘Content-Type’: ‘application/json’
}
};

var req1 = https.verzoek(opties functie(res) {

res.setEncoding(‘utf8’);

res.op(‘end’, function () {
console.log in op`Herzien met id: ${id} is succesvol verwijderd.`)
});
});

req1.op(‘error’, function (e) {
console.log(‘Probleem met een verzoek:”, e.bericht);
});

req1.end();
}

var postData = JSON.stringify({
replace_original: true,
bijlagen: [{
tekst: antwoord == ‘houden van’
? `De review (${id}) werd goedgekeurd!`
: `De review (${id}) werd afgewezen.`
}]
});

var url = getURL(json.response_url);

var options = {
hostnaam: url.hostnaam,
pad: url.padnaam,
methode: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’
}
};

var req = https.verzoek(opties functie(res) {

res.setEncoding(‘utf8’);

res.op(‘end’, function () {
callback(null, {
statusCode: 200
})
});
});

req.op(‘error’, function (e) {
console.log(‘Probleem met een verzoek:”, e.bericht);
});

req.schrijven(postData);
req.end();

callback(null, {
statusCode: 200
})
}

Ik analyseer de gebeurtenis lading en controleer of de actie waarde weigeren. Als het niet, het is noodzakelijk—niets aan te doen. Maar als dat zo is, moet ik bellen Netlify API ‘ s te verwijderen van de afgewezen review. Ik ben het ophalen van de review-ID zet eerder in de eerste bijlage tekst met de volgende regel:

json.original_message.bijlagen[0].tekst;

Eenmaal gedaan, kan ik deze verwijderen met een API-aanroep. Ik geef onze Slappe gebruikers feedback door te bellen met het antwoord URL.

Ik ben trots op het uiteindelijke workflow hier TBH:

5. De implementatie van de Gatsby site op Netlify

Hier, duwde ik alles op GitHub, en verkocht het aan Netlify met deze instellingen:

U kunt zien, hebben wij enkele van de omgevingsvariabelen met het proces.env.{variabele} notatie in de demo.

Dit zijn particuliere instellingen die we niet openbaar wilt maken. Voor het definiëren van jou direct, gaat u naar instellingen/zet in Netlify het dashboard, hit variabelen Bewerkenen voer de volgende handelingen uit:

  • netlify_access_token: De token die u eerder hebt gemaakt in netlify
  • site_id: url van Uw website, zonder het protocol
  • slack_webhook_url: Uw Slack app webhook URL

Website geïmplementeerd; tijd om te spelen!

Lees deze om te leren hoe te implementeren in een site op Netlify.

Live demo en GitHub repo