Le Front End : Utilisation de Gatsby.js et Node.js pour les mises à jour statiques du site
Publié: 2022-03-11Pour certaines exigences de projet, la génération de pages statiques n'est pas seulement suffisante , c'est aussi la plus efficace en termes de vitesse et d'évolutivité.
Dans la première moitié de cette série, nous avons combiné Node.js, Express, MongoDB, cron et Heroku pour fournir un back-end prêt pour CI qui utilise l'API de GitHub selon un calendrier quotidien. Nous sommes maintenant prêts à ajouter Gatsby au mix pour terminer notre projet de génération de page statique.
Développer le front-end : faites-en un site Web Gatsby
Étant donné que les sites Web Gatsby sont basés sur React, il est utile que vous sachiez déjà comment créer un site Web avec React.
Pour le style, j'ai préféré Bootstrap, reactstrap et react-markdown. Vous savez peut-être que les notes de publication dans GitHub sont stockées au format Markdown, d'où notre besoin d'un convertisseur.
Structure de projet de site Web statique
Notre structure de fichiers/dossiers sera la suivante :
A quoi servent ces fichiers ? Voyons voir:
-
env.development
etenv.production
sont des fichiers de configuration de variable d'environnement. - Le modèle
all-repositories.js
sera utilisé pour notre page d'accueil, contenant une liste de référentiels. - Le modèle
repository.js
sera utilisé pour afficher les détails d'un référentiel donné. -
gatsby-node.js
est l'endroit où nous consommons notre point de terminaison principal et exécutons nos méthodescreatePage
. -
package.json
, comme toujours, contient les dépendances et les propriétés du projet. -
global.css
est notre fichier de feuille de style principal.
Mise en place du site Web Gatsby
Comme pour notre back-end, exécutez npm install
(ou yarn
, si Yarn est installé) après avoir ajouté les dépendances requises au package.json
du front-end :
{ // ... "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" } // ... }
Les fichiers env.development
et env.production
n'ont que l'URL principale de leurs environnements correspondants. Le premier a :
API_URL=http://localhost:3000
…alors que la production a :
API_URL=https://[YOUR_UNIQUE_APP_NAME].herokuapp.com
gatsby-node.js
ne sera exécuté qu'une seule fois pendant que vous construisez votre code. Nous devons donc rassembler toutes les informations nécessaires à partir de notre back-end ici. Ensuite, la réponse sera utilisée avec nos modèles pour générer les pages statiques appropriées.
Dans notre cas, all-repositories.js
a besoin de tous les référentiels, et repository.js
besoin du référentiel correspondant pour chaque itération. Enfin, nous pouvons générer dynamiquement des chemins de page, en transmettant les paramètres de owner
et de name
du référentiel dans le champ de path
:
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 } }); }); };
Pour all-repositories.js
et repository.js
, si nous omettons le style, nous recueillons simplement des données à partir de pageContext
et les utilisons comme nous utilisons des paramètres dans React.
Dans all-repositories.js
, nous utiliserons le champ repositories
de pageContext
comme ceci :
export default ({pageContext: {repositories}}) => ( // ... <ListGroup> {/* Because the repositories parameter is a list, we are iterating over all items and using their fields */} {repositories.map(repository => (repository.tagName && <ListGroupItem className="repository-list-item"> // ... <Row> {`${repository.repositoryDescription}`} </Row> // ... </ListGroupItem> ))} </ListGroup> // ... );
Comme pour repository.js
, nous utiliserons à la place le champ repository
de pageContext
:
export default ({pageContext: {repository}}) => ( <div className="layout"> {repository.tagName && <ListGroupItem className="repository-list-item"> // ... <h1 className="release-notes">{`Release notes`}</h1> <hr/> {/* This the place where we will use Markdown-formatted release notes */} <ReactMarkdown source={`${repository.releaseDescription}`}/> </ListGroupItem> } // ... </div> );
Maintenant, assurez-vous que votre back-end est opérationnel. Vous vous souviendrez que pour ce projet, nous l'avons défini comme http://localhost:3000.
Ensuite, exécutez gatsby develop
à partir de la racine de votre projet frontal et ouvrez http://localhost:8000.
Si vous avez ajouté des référentiels (propriétaire/nom) à votre backend et exécuté la fonctionnalité update-via-GitHub-API au moins une fois, vous devriez voir quelque chose comme ceci :
Et après avoir cliqué sur l'un des référentiels, vous devriez voir quelque chose comme ceci :
Après nos modifications ci-dessus, notre implémentation frontale est terminée.
Génial! Il ne nous reste plus qu'à nous déployer.
Déploiement du frontal
Nous n'avons pas besoin d'apporter de modifications à notre application frontale dans cette partie. Nous allons simplement le déployer sur Netlify - vous aurez besoin d'un compte là-bas.
Mais d'abord, nous devons déployer notre code sur GitHub, GitLab ou Bitbucket. Comme pour le back-end, j'ai déployé mon code sur GitHub.
Ensuite, connectez-vous à Netlify et cliquez sur le bouton "Nouveau site de Git" sur votre tableau de bord. Suivez les étapes à l'écran pour sélectionner votre fournisseur Git et trouver votre référentiel.
Pour la dernière étape, si vous avez correctement structuré votre code, Netlify définira automatiquement la commande de construction et le répertoire de publication correctement comme suit :

Cliquez ensuite sur "Déployer le site". Il déploiera votre site sur un sous-domaine Netlify généré de manière aléatoire, mais vous pouvez le modifier à tout moment. J'ai changé mon déploiement en https://sample-create-page-api-gatsby.netlify.com, où vous pouvez trouver une démo en direct. de l'application terminée.
Jusqu'ici tout va bien. Mais comme il s'agit d'une application de page statique, nous devons la reconstruire quotidiennement pour la maintenir à jour.
Mise à jour quotidienne à l'aide d'un crochet de construction
Les crochets de construction dans Netlify fonctionnent comme des déclencheurs de construction, vous pouvez donc les déclencher depuis votre back-end une fois la tâche cron terminée. Pour ce faire, créez d'abord un crochet de construction dans Netlify.
Sous la section "Construire et déployer → Déploiement continu", vous pouvez trouver "Construire des hooks". Cliquez sur "Ajouter un crochet de construction".
Donnez-lui un nom et enregistrez-le. (J'ai appelé le mien build-from-backend
.) Ensuite, copiez le lien qu'il génère.
Ouvrons maintenant notre projet back-end et ajoutons ces quelques lignes au fichier cron.controller.js
. Nous envoyons simplement une requête POST
à l'URL build-hook de Netlify.
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'); }); } }
Ensuite, mettez à jour notre fonction updateDaily
:
function updateDaily() { RepositoryController.updateRepositories().then(() => { updateGatsby(); }); }
Enfin, mettez à jour notre fichier env.config.js
pour définir la propriété netlifyEndpoint
à collecter à partir des variables d'environnement :
"netlifyEndpoint": process.env.NETLIFY_BUILD_HOOK || ""
Maintenant, vous devrez définir la variable d'environnement NETLIFY_BUILD_HOOK
que vous avez copiée depuis Netlify il y a un instant. Dans Heroku, vous pouvez définir des variables d'environnement à partir de la section "paramètres" de votre application.
Après avoir poussé votre commit, l'application back-end enverra une demande de construction à Netlify et vos pages seront mises à jour quotidiennement, à la fin de votre travail cron. Voici à quoi devrait ressembler le référentiel après l'ajout de la fonctionnalité de crochet de construction, ainsi que les versions finales du référentiel principal et du référentiel frontal.
Comme touche finale au projet, nous montrerons comment utiliser une fonction AWS Lambda déclenchée par AWS CloudWatch qui réveillera votre back-end à temps pour chaque mise à jour quotidienne.
Demande simple AWS Lambda et AWS CloudWatch
AWS Lambda est une plateforme informatique sans serveur. Nous n'avons besoin que des bases mêmes de cette plate-forme pour nos besoins ici. Vous aurez besoin d'un compte AWS.
Tout d'abord, connectez-vous à AWS avec votre compte et recherchez la console de gestion Lambda. Par exemple, pour us-east-2
, il peut être trouvé à https://us-east-2.console.aws.amazon.com/lambda/home.
S'il n'est pas déjà sélectionné, rendez-vous dans la section « Fonctions » :
Ici, nous allons créer notre fonction à partir de zéro en cliquant sur "Créer une fonction". Donnons-lui un nom explicatif. Nous utiliserons Node.js comme langage d'exécution. Cliquez ensuite sur la prochaine "Créer une fonction" pour la finaliser.
Cela nous redirigera vers la page de la nouvelle fonction où nous pourrons écrire notre code dans index.js
.
Implémentons notre première fonction lambda. Comme nous n'avons pas de dépendances tierces, nous devons utiliser les modules de base de Node.js. (Si vous souhaitez plutôt activer les dépendances tierces, veuillez suivre ce guide d'AWS.)
Assurez-vous que le nom de la méthode exportée ( handler
dans ce cas) correspond au paramètre "Handler" dans la page :
Le reste est une simple requête GET
à votre back-end :
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); }); }); };
Assurez-vous de définir la variable d'environnement HEROKU_APP_URL
dans la page et enregistrez votre configuration :
Une dernière étape consiste à ajouter une règle de déclenchement CloudWatch pour exécuter cette fonction dix minutes avant chaque mise à jour quotidienne. Dans cette série d'articles, cela correspond à 23h50 :
Notre type de règle de déclenchement CloudWatch sera une « expression de planification » et, selon le format accepté, notre expression cron sera cron(50 23 * * ? *)
.
Nous avons maintenant configuré notre fonction AWS Lambda pour qu'elle soit déclenchée par notre règle CloudWatch.
Alimente maintenant nos pages Web statiques : Gatsby/React et Netlify
Avec un soupçon d'AWS Lambda/CloudWatch ajouté à notre back-end Node.js/MongoDB/Heroku, et Gatsby et Netlify générant et hébergeant notre front-end, notre application est complète !
J'ai partagé un lien de démonstration en direct plus tôt, mais n'hésitez pas à consulter également une version améliorée de mon prototype - il comporte quelques modifications supplémentaires que je sais que vous allez adorer.
Vous pouvez l'utiliser comme modèle pour des projets similaires. J'espère que ces articles vous aideront à prototyper vos applications de manière plus rapide et plus rentable. Merci d'avoir lu!