For noen prosjektkrav er generering av statisk side ikke bare tilstrekkelig , det er også mest effektiv når det gjelder hastighet og skalerbarhet.
I første halvdel av denne serien , kombinerte vi Node.js , Express, MongoDB, cron og Heroku å levere en CI-klar bakside som bruker GitHubs API i henhold til en daglig tidsplan. Nå er vi klare til å legge Gatsby til blandingen for å fullføre prosjektet vårt for generering av statisk side.
Fordi Gatsby nettsteder er basert på Reagere , det er nyttig hvis du allerede er kjent med hvordan du bygger et nettsted med React.
For styling foretrakk jeg Bootstrap, reactstrap og react-markdown. Det vet du kanskje utgivelsesmerknader i GitHub lagres i Markdown-format , derav vårt behov for en omformer.
Fil- / mappestrukturen vår vil være som følger:
Hva er disse filene til? La oss se:
env.development
og env.production
er konfigurasjonsfiler for miljøvariabler.all-repositories.js
malen vil bli brukt til hjemmesiden vår, som inneholder en liste over arkiver.repository.js
mal vil bli brukt til å vise detaljer for et gitt depot.gatsby-node.js
er der vi bruker vårt endepunkt og kjører vårt createPage
metoder.package.json
inneholder som alltid avhengigheter og prosjektegenskaper.global.css
er vår viktigste stilarkfil.Som med bakenden, løp npm install
(eller yarn
, hvis du har Garn installert) etter å ha lagt til de nødvendige avhengighetene til frontendens package.json
:
{ // ... 'dependencies': { 'axios': '^0.18.0', 'bootstrap': '^4.3.1', 'gatsby': '^2.0.0', 'react': '^16.5.1', 'react-dom': '^16.5.1', 'react-markdown': '^4.0.6', 'reactstrap': '^7.1.0' } // ... }
env.development
og env.production
filer har bare back-URL for deres tilsvarende miljøer. Førstnevnte har:
API_URL=http://localhost:3000
... mens produksjonen har:
API_URL=https://[YOUR_UNIQUE_APP_NAME].herokuapp.com
gatsby-node.js
kjøres bare én gang mens du bygger koden din. Så vi må samle all nødvendig informasjon fra bakenden her. Deretter vil svaret brukes med malene våre for å generere passende statiske sider.
I vårt tilfelle all-repositories.js
trenger alle arkiver, og repository.js
trenger tilsvarende lager for hver iterasjon. Endelig kan vi generere sidestier dynamisk, passere depotet owner
og name
parametere som en del av path
felt:
const axios = require('axios'); require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` }); const getRepositoryData = async () => { console.log(process.env.API_URL); return axios.get(`${process.env.API_URL}/repositories`); }; exports.createPages = async ({ actions: { createPage } }) => { let repositories = await getRepositoryData(); repositories = repositories.data; // Create a page that lists all repositories. createPage({ path: `/`, component: require.resolve('./src/templates/all-repositories.js'), context: { repositories } }); // Create a page for each repository. repositories.forEach(repository => { createPage({ path: `/repository/${repository.owner}/${repository.name}`, component: require.resolve('./src/templates/repository.js'), context: { repository } }); }); };
For all-repositories.js
og repository.js
, hvis vi utelater styling, samler vi ganske enkelt inn data fra pageContext
og bruke den når vi bruker parametere i React.
I all-repositories.js
vil vi bruke repositories
felt av pageContext
som dette:
export default ({pageContext: {repositories}}) => ( // ... {/* Because the repositories parameter is a list, we are iterating over all items and using their fields */} {repositories.map(repository => (repository.tagName && // ... {`${repository.repositoryDescription}`} // ... ))} // ... );
Når det gjelder repository.js
, vil vi i stedet bruke repository
felt av pageContext
:
export default ({pageContext: {repository}}) => ( {repository.tagName && // ...
{/* This the place where we will use Markdown-formatted release notes */} } // ... );
Nå, sørg for at bakenden din er i gang. Du husker at for dette prosjektet satte vi det som http: // localhost: 3000 .
Kjør deretter gatsby develop
fra roten til front-end-prosjektet og åpne http: // localhost: 8000 .
Hvis du la til noen arkiver (eier / navn) i bakenden og kjørte oppdateringen via GitHub-API-funksjonen minst en gang, bør du se noe som dette:
Og etter å ha klikket på et av depotene, bør du se noe sånt som dette:
Etter endringene våre ovenfor, vår frontend-implementering er ferdig .
Flott! Nå må vi bare distribuere.
Vi trenger ikke gjøre noen endringer i front-end-applikasjonen vår i denne delen. Vi vil ganske enkelt distribuere den til Netlify —Du trenger en konto der.
Men først må vi distribuere koden vår til GitHub, GitLab eller Bitbucket. Som med bakenden, Jeg distribuerte koden min til GitHub .
Logg deg deretter på Netlify og klikk på 'Nytt nettsted fra Git' -knappen på dashbordet. Følg trinnene på skjermen for å velge Git-leverandør og finne depotet ditt.
For det siste trinnet, hvis du strukturerte koden din riktig, vil Netlify automatisk sette build-kommandoen og publisere katalogen riktig som følger:
Klikk deretter på 'Distribuer nettsted'. Den vil distribuere nettstedet ditt til et tilfeldig generert Netlify-underdomenet, men du kan endre det når som helst - jeg endret distribusjonen min til https://sample-create-page-api-gatsby.netlify.com , hvor du kan finne en live demo av den ferdige appen.
Så langt så bra. Men fordi det er en statisk sideapplikasjon, må vi bygge den opp igjen hver dag for å holde den oppdatert.
Bygg kroker i Netlify fungerer som byggutløsere, slik at du kan utløse dem fra bakenden etter cron-jobben er ferdig. For å gjøre det må du først opprette en byggekrok i Netlify.
Under delen 'Bygg og distribuer → Kontinuerlig distribusjon' kan du finne 'Bygg kroker.' Klikk på 'Legg til byggekrok.'
Gi det et navn og lagre det. (Jeg ringte min build-from-backend
.) Kopier deretter lenken den genererer.
La oss nå åpne back-end-prosjektet vårt og legge til disse få linjene i cron.controller.js
fil. Vi sender rett og slett en POST
forespørsel om Netlifys URL-adresse for byggekrok.
const Axios = require('axios'); const Config = require('../config/env.config'); const NETLIFY_BUILD_HOOK_URI = Config.netlifyEndpoint; function updateGatsby() { if (NETLIFY_BUILD_HOOK_URI) { console.log('Gatsby build request will be send'); Axios.post(NETLIFY_BUILD_HOOK_URI).then(() => { console.log('Gatsby build request was successful'); }); } }
Oppdater deretter updateDaily
funksjon:
function updateDaily() { RepositoryController.updateRepositories().then(() => { updateGatsby(); }); }
Til slutt, oppdater vår env.config.js
fil for å angi netlifyEndpoint
eiendom som skal samles fra miljøvariabler:
'netlifyEndpoint': process.env.NETLIFY_BUILD_HOOK || ''
Nå må du angi NETLIFY_BUILD_HOOK
miljøvariabelen du kopierte fra Netlify for et øyeblikk siden. I Heroku, du kan angi miljøvariabler fra delen 'innstillinger' i applikasjonen .
Etter å ha presset på forpliktelsen, vil back-end-applikasjonen sende en byggeforespørsel til Netlify, og sidene dine blir oppdatert hver dag, på slutten av cron-jobben. Slik ser repoen ut etter å ha lagt til build hook-funksjonaliteten, sammen med de endelige versjonene av back-end repo og front-end repo .
Som siste prikk på prosjektet, viser vi hvordan du bruker en AWS Lambda-funksjon utløst av AWS CloudWatch som vil vekke ryggen din i tide for hver daglige oppdatering.
AWS Lambda er en serverløs databehandlingsplattform. Vi trenger bare det grunnleggende av denne plattformen for våre formål her. Du trenger en AWS-konto.
Logg deg først på AWS med kontoen din og finn Lambda Management Console. For eksempel, for us-east-2
, finner du den på https://us-east-2.console.aws.amazon.com/lambda/home .
Hvis det ikke allerede er valgt, går du til delen 'Funksjoner':
Her oppretter vi funksjonen vår fra bunnen av ved å klikke på 'Opprett funksjon.' La oss gi det et forklarende navn. Vi vil bruke Node.js som et kjøretidspråk. Klikk deretter neste “Opprett-funksjon” for å fullføre den.
Det vil omdirigere oss til den nye funksjonens side der vi kan skrive koden vår i index.js
.
La oss implementere vår første lambda-funksjon. Fordi vi ikke har noen avhengighet fra tredjepart, må vi bruke kjernemodulene til Node.js. (Hvis du vil aktivere avhengighet fra tredjepart i stedet, vær så snill følg denne guiden fra AWS .)
Forsikre deg om at det eksporterte metodenavnet (handler
i dette tilfellet) samsvarer med parameteren “Handler” på siden:
Resten av det er en enkel GET
forespørsel til din bakside:
const https = require('https'); exports.handler = async (event) => { return new Promise((resolve, reject) => { https.get(process.env.HEROKU_APP_URL, (resp) => { let data = ''; resp.on('data', (chunk) => { data += chunk; }); resp.on('end', () => { resolve(JSON.parse(data)); }); }).on('error', (err) => { reject('Error: ' + err.message); }); }); };
Forsikre deg om at du har angitt HEROKU_APP_URL
miljøvariabel på siden, og lagre konfigurasjonen:
Et siste trinn er å legge til en CloudWatch-utløserregel for å kjøre denne funksjonen ti minutter før hver daglige oppdatering - i denne artikkelserien som fungerer til 23:50:
Vår CloudWatch utløserregeltype vil være et 'Planlegg uttrykk', og i henhold til det aksepterte formatet, vil vårt cronuttrykk være cron(50 23 * * ? *)
.
Vi har nå konfigurert AWS Lambda-funksjonen vår til å utløses av CloudWatch-regelen vår.
Med et dash AWS Lambda / CloudWatch lagt til Node.js / MongoDB / Heroku bakenden, og Gatsby og Netlify genererer og vert for frontend, er appen vår komplett!
Jeg delte en live demo-lenke tidligere, men sjekk også gjerne ut en forbedret versjon av prototypen min —Det har noen ekstra endringer jeg vet at du vil elske.
Du kan bruke dette som en tegning for lignende prosjekter - jeg håper disse artiklene vil hjelpe deg med å prototype appene dine på en raskere og mer kostnadseffektiv måte. Takk for at du leste!
Gatsby.js (eller ganske enkelt 'Gatsby') er et åpen kildekode, React-basert statisk rammeverk for generering av nettsteder.
Netlify er en statisk vert som ligner på GitHub Pages, men med noen ekstra funksjoner.
En statisk generator genererer et statisk nettsted fra en mal ved hjelp av gjeldende data. Det resulterende nettstedet er veldig raskt, men å kunne generere det med jevne mellomrom betyr at det automatisk kan holde seg oppdatert.