portaldacalheta.pt
  • Principal
  • Gestion De L'ingénierie
  • Conseils Et Outils
  • Rise Of Remote
  • Agile
Back-End

Le back-end: utilisation de Gatsby.js et Node.js pour les mises à jour statiques du site



Dans cette série d'articles, nous développerons un prototype de site Web à contenu statique. Il générera des pages HTML statiques simples mises à jour quotidiennement pour les référentiels GitHub populaires afin de suivre leurs dernières versions. Les frameworks de génération de pages Web statiques disposent d'excellentes fonctionnalités pour y parvenir. Nous utiliserons Gatsby.js, l'un des plus populaires.

Dans Gatsby, il existe de nombreuses façons de collecter des données pour un front-end sans avoir de back-end (sans serveur), Plateformes CMS sans tête et Plugins sources Gatsby parmi eux. Mais nous allons implémenter un back-end pour stocker des informations de base sur les référentiels GitHub et leurs dernières versions. Ainsi, nous aurons un contrôle total sur notre back-end et notre front-end.



Je vais également couvrir un ensemble d'outils pour déclencher une mise à jour quotidienne de votre application. Vous pouvez également le déclencher manuellement ou chaque fois qu'un événement spécifique se produit.



Notre application frontale sera exécutée sur Netlify, et l'application back-end fonctionnera sur Heroku en utilisant un plan gratuit. Il dormira périodiquement : 'Quand quelqu'un accède à l'application, le gestionnaire de dynamomètre réveillera automatiquement le dynamomètre Web pour exécuter le type de processus Web.' Donc, nous pouvons le réveiller via AWS Lambda et AWS CloudWatch. Au moment d'écrire ces lignes, c'est le moyen le plus rentable d'avoir un prototype en ligne 24/7.



Exemple de site Web statique de nœud: à quoi s'attendre

Pour que ces articles restent concentrés sur un seul sujet, je ne traiterai pas de l'authentification, de la validation, de l'évolutivité ou d'autres sujets généraux. La partie codage de cet article sera aussi simple que possible. La structure du projet et l'utilisation du bon ensemble d'outils sont plus importantes.

Dans cette première partie de la série, nous développerons et déploierons notre application back-end. Dans La seconde partie , nous développerons et déploierons notre application frontale et déclencherons des builds quotidiens.



Le back-end Node.js

L'application back-end sera écrite en Node.js (pas obligatoire, mais par souci de simplicité) et toutes les communications se feront via les API REST. Nous ne collecterons pas de données à partir du front-end de ce projet. (Si cela vous intéresse, jetez un œil à Formulaires Gatsby .)

Tout d'abord, nous allons commencer par implémenter un back-end d'API REST simple qui expose les opérations CRUD de la collection de référentiels dans notre MongoDB. Ensuite, nous planifierons une tâche cron qui consomme l'API GitHub v4 (GraphQL) afin de mettre à jour les documents de cette collection. Ensuite, nous déploierons tout cela sur le cloud Heroku. Enfin, nous déclencherons une reconstruction du front-end à la fin de notre tâche cron.



Le frontal Gatsby.js

Dans le deuxième article, nous nous concentrerons sur la mise en œuvre du createPages FEU . Nous rassemblerons tous les référentiels du back-end et générerons une seule page d'accueil contenant une liste de tous les référentiels, plus une page pour chaque document de référentiel renvoyé. Alors bien déployer notre front-end sur Netlify .

Depuis AWS Lambda et AWS CloudWatch

Cette partie n'est pas obligatoire si votre application ne se met pas en veille. Sinon, vous devez vous assurer que votre back-end est opérationnel au moment de la mise à jour des référentiels. En guise de solution, vous pouvez créer une planification cron sur AWS CloudWatch 10 minutes avant votre mise à jour quotidienne et la lier en tant que déclencheur à votre GET méthode dans AWS Lambda. L'accès à l'application back-end réveillera l'instance Heroku. Plus de détails seront à la fin du deuxième article.



Voici l'architecture que nous allons implémenter:

Diagramme d



Hypothèses

Je suppose que les lecteurs de cet article ont des connaissances dans les domaines suivants:

  • HTML
  • CSS
  • JavaScript
  • API REST
  • MongoDB
  • Aller
  • Node.js

C’est aussi bien si vous savez:



  • Express.js
  • Mangouste
  • API GitHub v4 (GraphQL)
  • Heroku, AWS ou toute autre plateforme cloud
  • Réagir

Plongeons-nous dans la mise en œuvre du back-end. Nous allons le diviser en deux tâches. Le premier consiste à préparer les points de terminaison de l'API REST et à les lier à notre collection de référentiels. La seconde consiste à implémenter une tâche cron qui consomme l'API GitHub et met à jour la collection.

Développement du back-end du générateur de site statique Node.js, Étape 1: Une API REST simple

Nous utiliserons Express pour notre cadre d'application Web et Mongoose pour notre connexion MongoDB. Si vous connaissez Express et Mongoose, vous pourrez peut-être passer à l'étape 2.

(D'un autre côté, si vous avez besoin de plus de familiarité avec Express, vous pouvez consulter le guide de démarrage officiel Express ; si vous n'êtes pas sur Mongoose, le guide de démarrage officiel Mongoose devrait être utile.)

Structure du projet

La hiérarchie des fichiers / dossiers de notre projet sera simple:

Une liste de dossiers de la racine du projet, montrant les dossiers config, controller, model et node_modules, ainsi que quelques fichiers racine standard tels que index.js et package.json. Les fichiers des trois premiers dossiers suivent la convention de dénomination consistant à répéter le nom du dossier dans chaque nom de fichier dans un dossier donné.

Plus en détail:

  • env.config.js est le fichier de configuration des variables d'environnement
  • routes.config.js sert à mapper les points de terminaison de repos
  • repository.controller.js contient des méthodes pour travailler sur notre modèle de référentiel
  • repository.model.js contient le schéma MongoDB des opérations de référentiel et CRUD
  • index.js est une classe d'initialisation
  • package.json contient des dépendances et des propriétés de projet

la mise en oeuvre

Exécuter npm install (ou yarn, si vous avez installé Yarn) après avoir ajouté ces dépendances à package.json:

{ // ... 'dependencies': { 'body-parser': '1.7.0', 'express': '^4.8.7', 'moment': '^2.17.1', 'moment-timezone': '^0.5.13', 'mongoose': '^5.1.1', 'node-uuid': '^1.4.8', 'sync-request': '^4.0.2' } // ... }

Notre env.config.js le fichier n'a que port, environment (dev ou prod), et mongoDbUri propriétés pour l'instant:

module.exports = ;

routes.config.js contient des mappages de requêtes et appellera la méthode correspondante de notre contrôleur:

const RepositoryController = require('../controller/repository.controller'); exports.routesConfig = function(app) { app.post('/repositories', [ RepositoryController.insert ]); app.get('/repositories', [ RepositoryController.list ]); app.get('/repositories/:id', [ RepositoryController.findById ]); app.patch('/repositories/:id', [ RepositoryController.patchById ]); app.delete('/repositories/:id', [ RepositoryController.deleteById ]); };

Le repository.controller.js file est notre couche de service. Sa responsabilité est d'appeler la méthode correspondante de notre modèle de référentiel:

const RepositoryModel = require('../model/repository.model'); exports.insert = (req, res) => { RepositoryModel.create(req.body) .then((result) => { res.status(201).send({ id: result._id }); }); }; exports.findById = (req, res) => { RepositoryModel.findById(req.params.id) .then((result) => { res.status(200).send(result); }); }; exports.list = (req, res) => { RepositoryModel.list() .then((result) => { res.status(200).send(result); }) }; exports.patchById = (req, res) => { RepositoryModel.patchById(req.params.id, req.body) .then(() => { res.status(204).send({}); }); }; exports.deleteById = (req, res) => { RepositoryModel.deleteById(req.params.id, req.body) .then(() => { res.status(204).send({}); }); };

repository.model.js gère la connexion MongoDb et les opérations CRUD pour le modèle de référentiel. Les champs du modèle sont:

comment obtenir un terminal bloomberg
  • owner: Le propriétaire du référentiel (société ou utilisateur)
  • name: Le nom du référentiel
  • createdAt: La date de création de la dernière version
  • resourcePath: Le dernier chemin de version
  • tagName: La dernière balise de version
  • releaseDescription: Notes de version
  • homepageUrl: URL d'accueil du projet
  • repositoryDescription: La description du référentiel
  • avatarUrl: L'URL de l'avatar du propriétaire du projet
const Mongoose = require('mongoose'); const Config = require('../config/env.config'); const MONGODB_URI = Config.mongoDbUri; Mongoose.connect(MONGODB_URI, { useNewUrlParser: true }); const Schema = Mongoose.Schema; const repositorySchema = new Schema({ owner: String, name: String, createdAt: String, resourcePath: String, tagName: String, releaseDescription: String, homepageUrl: String, repositoryDescription: String, avatarUrl: String }); repositorySchema.virtual('id').get(function() { return this._id.toHexString(); }); // Ensure virtual fields are serialised. repositorySchema.set('toJSON', { virtuals: true }); repositorySchema.findById = function(cb) { return this.model('Repository').find({ id: this.id }, cb); }; const Repository = Mongoose.model('repository', repositorySchema); exports.findById = (id) => { return Repository.findById(id) .then((result) => { if (result) { result = result.toJSON(); delete result._id; delete result.__v; return result; } }); }; exports.create = (repositoryData) => { const repository = new Repository(repositoryData); return repository.save(); }; exports.list = () => { return new Promise((resolve, reject) => { Repository.find() .exec(function(err, users) { if (err) { reject(err); } else { resolve(users); } }) }); }; exports.patchById = (id, repositoryData) => { return new Promise((resolve, reject) => { Repository.findById(id, function(err, repository) { if (err) reject(err); for (let i in repositoryData) { repository[i] = repositoryData[i]; } repository.save(function(err, updatedRepository) { if (err) return reject(err); resolve(updatedRepository); }); }); }) }; exports.deleteById = (id) => { return new Promise((resolve, reject) => { Repository.deleteOne({ _id: id }, (err) => { if (err) { reject(err); } else { resolve(err); } }); }); }; exports.findByOwnerAndName = (owner, name) => { return Repository.find({ owner: owner, name: name }); };

Voici ce que nous avons après notre premier commit: Une connexion MongoDB et nos opérations REST .

Nous pouvons exécuter notre application avec la commande suivante:

node index.js

Essai

Pour les tests, envoyez les requêtes à localhost:3000 (en utilisant par exemple Postman ou cURL):

Insérer un référentiel (uniquement les champs obligatoires)

Publier: http: // localhost: 3000 / repositories

Corps:

{ 'owner' : 'facebook', 'name' : 'react' }

Obtenir des référentiels

Avoir: http: // localhost: 3000 / repositories

Obtenir par ID

Avoir: http: // localhost: 3000 / repositories /: id

Patch par ID

Pièce: http: // localhost: 3000 / repositories /: id

Corps:

{ 'owner' : 'facebook', 'name' : 'facebook-android-sdk' }

Cela fonctionne, il est temps d'automatiser les mises à jour.

Développement du back-end du générateur de site statique Node.js, étape 2: un travail Cron pour mettre à jour les versions du référentiel

Dans cette partie, nous allons configurer un simple travail cron (qui commencera à minuit UTC) pour mettre à jour les référentiels GitHub que nous avons insérés dans notre base de données. Nous avons ajouté uniquement le owner et name paramètres uniquement dans notre exemple ci-dessus, mais ces deux champs nous suffisent pour accéder aux informations générales sur un référentiel donné.

Afin de mettre à jour nos données, nous devons consommer l'API GitHub. Pour cette partie, il est préférable de se familiariser avec GraphQL et v4 de l'API GitHub .

Nous devons également créer un jeton d'accès GitHub . Les portées minimales requises pour cela sont:

Les portées de jetons GitHub dont nous avons besoin sont repo: status, repo_deployment, public_repo, read: org et read: user.

Cela générera un jeton et nous pourrons envoyer des requêtes à GitHub avec lui.

Revenons maintenant à notre code.

Nous avons deux nouvelles dépendances dans package.json:

  • 'axios': '^0.18.0' est un client HTTP, nous pouvons donc faire des requêtes à l'API GitHub
  • 'cron': '^1.7.0' est un planificateur de tâches cron

Comme d'habitude, exécutez npm install ou yarn après avoir ajouté des dépendances.

Nous aurons également besoin de deux nouvelles propriétés dans config.js:

  • 'githubEndpoint': 'https://api.github.com/graphql'
  • 'githubAccessToken': process.env.GITHUB_ACCESS_TOKEN (vous devrez définir la variable d'environnement GITHUB_ACCESS_TOKEN avec votre propre jeton d'accès personnel)

Créez un nouveau fichier sous le controller dossier avec le nom cron.controller.js. Il appellera simplement le updateResositories méthode de repository.controller.js aux heures prévues:

const RepositoryController = require('../controller/repository.controller'); const CronJob = require('cron').CronJob; function updateDaily() { RepositoryController.updateRepositories(); } exports.startCronJobs = function () { new CronJob('0 0 * * *', function () {updateDaily()}, null, true, 'UTC'); };

Les modifications finales pour cette partie seront dans repository.controller.js. Par souci de concision, nous allons le concevoir de manière à mettre à jour tous les dépôts à la fois. Mais si vous avez un grand nombre de référentiels, vous pouvez dépasser le limitations des ressources de l'API de GitHub . Si tel est le cas, vous devrez le modifier pour qu'il s'exécute par lots limités, répartis dans le temps.

L'implémentation tout-à-une de la fonctionnalité de mise à jour ressemblera à ceci:

async function asyncUpdate() { await RepositoryModel.list().then((array) => { const promises = array.map(getLatestRelease); return Promise.all(promises); }); } exports.updateRepositories = async function update() { console.log('GitHub Repositories Update Started'); await asyncUpdate().then(() => { console.log('GitHub Repositories Update Finished'); }); };

Enfin, nous allons appeler le point de terminaison et mettre à jour le modèle de référentiel.

Le getLatestRelease La fonction générera une requête GraphQL et appellera l'API GitHub. La réponse de cette demande sera ensuite traitée dans le updateDatabase fonction.

async function updateDatabase(responseData, owner, name) { let createdAt = ''; let resourcePath = ''; let tagName = ''; let releaseDescription = ''; let homepageUrl = ''; let repositoryDescription = ''; let avatarUrl = ''; if (responseData.repository.releases) { createdAt = responseData.repository.releases.nodes[0].createdAt; resourcePath = responseData.repository.releases.nodes[0].resourcePath; tagName = responseData.repository.releases.nodes[0].tagName; releaseDescription = responseData.repository.releases.nodes[0].description; homepageUrl = responseData.repository.homepageUrl; repositoryDescription = responseData.repository.description; if (responseData.organization && responseData.organization.avatarUrl) { avatarUrl = responseData.organization.avatarUrl; } else if (responseData.user && responseData.user.avatarUrl) { avatarUrl = responseData.user.avatarUrl; } const repositoryData = { owner: owner, name: name, createdAt: createdAt, resourcePath: resourcePath, tagName: tagName, releaseDescription: releaseDescription, homepageUrl: homepageUrl, repositoryDescription: repositoryDescription, avatarUrl: avatarUrl }; await RepositoryModel.findByOwnerAndName(owner, name) .then((oldGitHubRelease) => { if (!oldGitHubRelease[0]) { RepositoryModel.create(repositoryData); } else { RepositoryModel.patchById(oldGitHubRelease[0].id, repositoryData); } console.log(`Updated latest release: http://github.com${repositoryData.resourcePath}`); }); } } async function getLatestRelease(repository) { const owner = repository.owner; const name = repository.name; console.log(`Getting latest release for: http://github.com/${owner}/${name}`); const query = ` query { organization(login: '${owner}') { avatarUrl } user(login: '${owner}') { avatarUrl } repository(owner: '${owner}', name: '${name}') { homepageUrl description releases(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) { nodes { createdAt resourcePath tagName description } } } }`; const jsonQuery = JSON.stringify({ query }); const headers = { 'User-Agent': 'Release Tracker', 'Authorization': `Bearer ${GITHUB_ACCESS_TOKEN}` }; await Axios.post(GITHUB_API_URL, jsonQuery, { headers: headers }).then((response) => { return updateDatabase(response.data.data, owner, name); }); }

Après notre deuxième commit, nous aurons implémenté un planificateur cron pour obtenir des mises à jour quotidiennes de nos dépôts GitHub .

Nous avons presque terminé avec le back-end. Mais la dernière étape devrait être effectuée après la mise en œuvre du front-end, nous allons donc la couvrir dans le prochain article.

Déploiement du back-end Node Static Site Generator sur Heroku

Dans cette étape, nous déploierons notre application sur Heroku, donc vous devrez créer un compte avec eux si vous n'en avez pas déjà. Si nous lions notre compte Heroku à GitHub, il sera beaucoup plus facile pour nous d'avoir un déploiement continu. À cette fin, J'héberge mon projet sur GitHub .

Après vous être connecté à votre compte Heroku, ajoutez une nouvelle application depuis le tableau de bord:

Choisir

Donnez-lui un nom unique:

Nommer votre application dans Heroku.

Vous serez redirigé vers une section de déploiement. Sélectionnez GitHub comme méthode de déploiement, recherchez votre référentiel, puis cliquez sur le bouton «Connecter»:

Lier votre nouveau dépôt GitHub à votre application Heroku.

Pour plus de simplicité, vous pouvez activer les déploiements automatiques. Il se déploiera chaque fois que vous enverrez un commit à votre dépôt GitHub:

Activation des déploiements automatiques dans Heroku.

Nous devons maintenant ajouter MongoDB en tant que ressource. Accédez à l'onglet Ressources et cliquez sur 'Rechercher d'autres modules complémentaires'. (J'utilise personnellement mLab mongoDB.)

Ajout d

Installez-le et entrez le nom de votre application dans la zone de saisie 'Application à approvisionner':

La page de mise à disposition du module complémentaire mLab MongoDB dans Heroku.

Enfin, nous devons créer un fichier nommé Procfile au niveau racine de notre projet, qui spécifie les commandes qui sont exécutées par l'application lorsque Heroku la démarre.

Notre Procfile est aussi simple que ceci:

web: node index.js

Créez le fichier et validez-le. Une fois que vous avez poussé le commit, Heroku déploiera automatiquement votre application, qui sera accessible en tant que https://[YOUR_UNIQUE_APP_NAME].herokuapp.com/.

Pour vérifier si cela fonctionne, nous pouvons envoyer les mêmes demandes que celles que nous avons envoyées à localhost.

Node.js, Express, MongoDB, Cron et Heroku: nous en sommes à mi-chemin!

Après notre troisième engagement, voici à quoi ressemblera notre repo .

Jusqu'à présent, nous avons mis en œuvre le Node.js / API REST basée sur Express sur notre back-end, le programme de mise à jour qui utilise l'API de GitHub et une tâche cron pour l'activer. Ensuite, nous avons déployé notre back-end qui fournira plus tard des données pour notre générateur de contenu Web statique en utilisant Heroku avec un crochet pour une intégration continue. Vous êtes maintenant prêt pour La seconde partie , où nous implémentons le front-end et complétons l'application!

En relation: Les 10 erreurs les plus courantes commises par les développeurs Node.js

Comprendre les bases

Que sont les pages Web statiques et dynamiques?

Après la publication, les pages Web statiques contiennent les mêmes données pour toutes les sessions. Dans les pages Web dynamiques, les données peuvent être mises à jour à la volée.

Pourquoi Node est-il populaire?

Node.js est léger, rapide, évolutif, open source et bien pris en charge par sa communauté.

Quel est le but de Node.js?

Node.js sert d'environnement d'exécution principal pour créer des applications Web évolutives, légères, asynchrones et basées sur les événements avec JavaScript.

Quels sont les avantages de Node.js?

Node.js utilise le même langage (JavaScript) pour le côté serveur qui est normalement utilisé dans le navigateur. Il est léger et conçu pour utiliser des opérations d'E / S non bloquantes pendant le traitement des demandes.

Quelle est l'importance de Node.js?

En tant que membre de la populaire pile MEAN — MongoDB, Express.js, Angular et Node.js — Node.js est important pour développer des applications Web évolutives et hautes performances avec JavaScript.

Quels sont les avantages de GraphQL?

Certains des avantages de GraphQL incluent la collecte uniquement de ce dont vous avez besoin sur le serveur, l'obtention de plusieurs ressources en une seule demande et le fait que ses API sont auto-documentées.

Pourquoi GraphQL est-il utilisé?

GraphQL permet un prototypage et un déploiement de production rapides. De plus, il utilise un seul point de terminaison pour toutes les ressources, ce qui facilite la communication client-serveur.

Quel est le but d'Heroku?

Heroku est une plate-forme cloud axée sur la rationalisation du lancement et de la mise à l'échelle des applications.

Introduction à la théorie de l'apprentissage automatique et à ses applications: un didacticiel visuel avec des exemples

Science Des Données Et Bases De Données

Introduction à la théorie de l'apprentissage automatique et à ses applications: un didacticiel visuel avec des exemples
L'innovation de la banque numérique à l'ère des perturbations

L'innovation de la banque numérique à l'ère des perturbations

Rentabilité Et Efficacité

Articles Populaires
API de réseaux sociaux: le portail Internet vers le monde réel
API de réseaux sociaux: le portail Internet vers le monde réel
Explorer les raisons de la critique du Design Thinking
Explorer les raisons de la critique du Design Thinking
La concurrence et la tolérance aux pannes simplifiées: un didacticiel Akka avec des exemples
La concurrence et la tolérance aux pannes simplifiées: un didacticiel Akka avec des exemples
Dix fonctionnalités Kotlin pour booster le développement Android
Dix fonctionnalités Kotlin pour booster le développement Android
Soutenir l'offre technologique grâce à l'éducation STEM
Soutenir l'offre technologique grâce à l'éducation STEM
 
État de l'industrie Fintech (avec infographie)
État de l'industrie Fintech (avec infographie)
DevOps: qu'est-ce que c'est et pourquoi c'est important
DevOps: qu'est-ce que c'est et pourquoi c'est important
Scala vs Java: pourquoi devrais-je apprendre Scala?
Scala vs Java: pourquoi devrais-je apprendre Scala?
Qu'est-ce qu'un round down et comment en éviter un
Qu'est-ce qu'un round down et comment en éviter un
Création d'illustrations époustouflantes avec Sketch et Looper en un rien de temps
Création d'illustrations époustouflantes avec Sketch et Looper en un rien de temps
Articles Populaires
  • après qu'un programme est codé, il doit être
  • les méthodes d'actualisation des flux de trésorerie pour la budgétisation des immobilisations se concentrent sur
  • c corp vs s impôts sur les sociétés
  • comment fonctionne ruby ​​on rails
  • tutoriel magento 2 pour développeur
  • une llc qui a peut choisir d'être imposée en tant que société de personnes ou en tant que société.
Catégories
  • Gestion De L'ingénierie
  • Conseils Et Outils
  • Rise Of Remote
  • Agile
  • © 2022 | Tous Les Droits Sont Réservés

    portaldacalheta.pt