Créer une application simple pour débutant avec Node, Bootstrap et MongoDB – SitePoint – Gratuit : Audit complet de votre site internet

Avant de commencer !

MongoDB Compass connecté à localhost: 27107
Share on facebook
Share on twitter
Share on pinterest

Si vous débutez avec Node.js et que vous voulez vous essayer à la création d’une application Web, les choses peuvent souvent devenir un peu écrasantes. Une fois que vous avez dépassé le «Bonjour, monde!» didacticiels, une grande partie du matériel disponible contient du code de copier-coller, avec peu ou pas d’explications sur ce que vous faites ou pourquoi.

Cela signifie qu’au moment où vous avez terminé, vous avez construit quelque chose de beau et de brillant, mais vous avez également relativement peu de plats à emporter que vous pouvez appliquer à votre prochain projet.

Dans ce didacticiel, je vais adopter une approche légèrement différente. À partir de zéro, je vais vous montrer comment créer une application Web sans fioritures à l’aide de Node.js, mais au lieu de me concentrer sur le résultat final, je vais me concentrer sur un éventail de choses que vous êtes susceptible de rencontrer lors de la construction. une application du monde réel. Il s’agit notamment du routage, des modèles, du traitement des formulaires, de l’interaction avec une base de données et même de l’authentification de base.

Ce ne sera pas un JavaScript 101. Si c’est le genre de chose que vous recherchez, regardez ici. Cependant, il conviendra aux personnes qui se sentent raisonnablement confiantes avec le langage JavaScript et qui cherchent à faire leurs premiers pas dans Node.js.

Ce que nous allons construire

Nous utiliserons Node.js et le framework Express pour créer un simple formulaire d’inscription avec validation de base, qui conserve ses données dans une base de données MongoDB. Nous ajouterons une vue pour répertorier les enregistrements réussis, que nous protégerons avec une authentification HTTP de base, et nous utiliserons Bootstrap pour ajouter un style. Le didacticiel est structuré de manière à ce que vous puissiez suivre étape par étape. Cependant, si vous souhaitez aller de l’avant et voir le résultat final, le code de ce didacticiel est également disponible sur GitHub.

Configuration de base

Avant de pouvoir commencer à coder, nous devons installer Node, npm et MongoDB sur nos machines. Je n’entrerai pas dans les détails des différentes instructions d’installation, mais si vous avez des problèmes pour vous installer, veuillez visiter nos forums et demander de l’aide.

Node.js

De nombreux sites Web vous recommanderont de vous rendre sur la page de téléchargement officielle de Node et de récupérer les binaires Node de votre système. Bien que cela fonctionne, je vous suggère d’utiliser un gestionnaire de versions à la place. Il s’agit d’un programme qui vous permet d’installer plusieurs versions de Node et de basculer entre elles à volonté. L’utilisation d’un gestionnaire de versions présente plusieurs avantages. Par exemple, cela annule les problèmes d’autorisation potentiels qui, autrement, vous verraient installer des packages avec des droits d’administrateur.

Si vous souhaitez suivre la voie du gestionnaire de versions, veuillez consulter notre astuce: Installer plusieurs versions de Node.js à l’aide de nvm. Sinon, récupérez les binaires appropriés pour votre système à partir du lien ci-dessus et installez-les.

npm

npm est un gestionnaire de packages JavaScript fourni avec Node, donc aucune installation supplémentaire n’est nécessaire ici. Nous utiliserons assez largement npm tout au long de ce didacticiel. Si vous avez besoin d’une mise à jour, veuillez consulter le Guide du débutant de npm – le gestionnaire de packages de nœuds.

MongoDB

MongoDB est une base de données de documents qui stocke les données dans des documents flexibles de type JSON. Si vous n’avez jamais travaillé avec Mongo auparavant, vous aimerez peut-être consulter notre introduction conviviale à MongoDB.

Le moyen le plus rapide de devenir opérationnel avec Mongo est d’utiliser un service tel que mLabs. Ils ont un plan sandbox gratuit qui fournit une base de données unique avec 0,5 Go de stockage exécuté sur une machine virtuelle partagée. C’est plus que suffisant pour une application simple avec une poignée d’utilisateurs. Si cela vous semble la meilleure option, veuillez consulter leur guide de démarrage rapide.

Vous pouvez également installer Mongo localement. Pour ce faire, veuillez visiter la page de téléchargement officielle et télécharger la version correcte du serveur de communauté pour votre système d’exploitation. Il y a un lien vers des instructions d’installation spécifiques au système d’exploitation sous chaque lien de téléchargement, que vous pouvez consulter en cas de problème.

Une interface graphique MongoDB

Bien que cela ne soit pas strictement nécessaire pour suivre ce didacticiel, vous pouvez également installer Compass, l’interface graphique officielle de MongoDB. Cet outil vous aide à visualiser et à manipuler vos données, vous permettant d’interagir avec des documents avec une fonctionnalité CRUD complète.

Vérifiez que tout est installé correctement

Pour vérifier que Node et npm sont installés correctement, ouvrez votre terminal et tapez:

node -v

suivi par:

npm -v

Cela affichera le numéro de version de chaque programme (12.14.1 et 6.13.6 respectivement au moment de la rédaction).

Si vous avez installé Mongo localement, vous pouvez vérifier le numéro de version en utilisant:

mongo --version

Cela devrait produire un tas d’informations, y compris le numéro de version (4.2.2 au moment de la rédaction).

Vérifiez la connexion à la base de données à l’aide de la boussole

Si vous avez installé Mongo localement, vous démarrez le serveur en tapant la commande suivante dans un terminal:

mongod

Ensuite, ouvrez Compass. Vous devriez pouvoir accepter les valeurs par défaut (serveur: localhost, port: 27017), appuyez sur la RELIER et établissez une connexion avec le serveur de base de données.

MongoDB Compass connecté à localhost: 27107

MongoDB Compass connecté à localhost

Notez que les bases de données admin, config et local sont créés automatiquement.

Utilisation d’une solution hébergée dans le cloud

Si vous utilisez mLabs, créez un abonnement à la base de données (comme décrit dans leur guide de démarrage rapide), puis notez les détails de la connexion.

Ouvrez Compass, cliquez sur Nouvelle connexion, puis Remplissez les champs de connexion individuellement. Sélectionner Identifiant Mot de passe comme méthode d’authentification, puis remplissez le reste des détails. Enfin, cliquez sur RELIER et vous devriez partir pour les courses.

Remarque: si vous souhaitez utiliser une chaîne de connexion, elle devrait ressembler à ceci: mongodb://:@ds211709.mlab.com:11709/?authSource=.

MongoDB Compass connecté aux mLabs

MongoDB Compass connecté aux mLabs

Notez que j’ai appelé ma base de données sp-node-article. Vous pouvez appeler le vôtre comme vous le souhaitez.

Initialiser l’application

Lorsque tout est correctement configuré, la première chose que nous devons faire est d’initialiser notre nouveau projet. Pour ce faire, créez un dossier nommé demo-node-app, entrez ce répertoire et saisissez ce qui suit dans un terminal:

npm init -y

Cela créera et remplira automatiquement un package.json fichier à la racine du projet. Nous pouvons utiliser ce fichier pour spécifier nos dépendances et créer divers scripts npm, ce qui facilitera notre flux de travail de développement.

Installer Express

Express est un cadre d’application Web léger pour Node.js, qui nous fournit un ensemble robuste de fonctionnalités pour l’écriture d’applications Web. Ces fonctionnalités incluent des éléments tels que la gestion des itinéraires, l’intégration du moteur de modèle et une infrastructure middleware, qui nous permet d’effectuer des tâches supplémentaires sur les objets de demande et de réponse. Il n’y a rien que vous puissiez faire dans Express que vous ne pourriez pas faire dans Node.js ordinaire, mais en utilisant Express, nous n’avons pas à réinventer la roue et cela réduit le passe-partout.

Installons donc Express. Pour ce faire, exécutez ce qui suit dans votre terminal:

npm install express

Cela verra Express ajouté à la dependencies section du package.json fichier. Cela signale à toute autre personne exécutant notre code qu’Express est un package dont notre application a besoin pour fonctionner correctement.

Installer nodemon

nodemon est un outil pratique. Il surveillera les fichiers dans le répertoire dans lequel il a été démarré et s’il détecte des modifications, il redémarrera automatiquement votre application Node (ce qui signifie que vous n’en avez pas besoin). Contrairement à Express, nodemon n’est pas quelque chose que l’application nécessite pour fonctionner correctement (elle nous aide simplement au développement), alors installez-le en utilisant:

npm install --save-dev nodemon

Cela ajoutera nodemon à la dev-dependencies section du package.json fichier.

Créer des fichiers initiaux

Nous avons presque terminé la configuration. Tout ce que nous devons faire maintenant est de créer quelques fichiers initiaux avant de lancer l’application.

dans le demo-node-app dossier créer un app.js fichier et un start.js fichier. Créez également un routes dossier, avec un index.js fichier à l’intérieur. Une fois que vous avez terminé, les choses devraient ressembler à ceci:

.
├── app.js
├── node_modules
│   └── ...
├── package.json
├── package-lock.json
├── routes
│   └── index.js
└── start.js

Maintenant, ajoutons du code à ces fichiers.

Dans app.js:

const express = require('express');
const routes = require('./routes/index');

const app = express();
app.use("https://www.sitepoint.com/", routes);

module.exports = app;

Ici, nous importons à la fois le express module et (la valeur d’exportation de) notre fichier de routes dans l’application. le require La fonction que nous utilisons pour ce faire est une fonction Node intégrée qui importe un objet à partir d’un autre fichier ou module. Si vous souhaitez une mise à jour sur l’importation et l’exportation de modules, lisez Comprendre module.exports et exports dans Node.js.

Après cela, nous créons une nouvelle application Express à l’aide de la fonction express et l’affectons à un app variable. Nous indiquons ensuite à l’application que, chaque fois qu’elle reçoit une demande de barre oblique, elle doit utiliser le fichier routes.

Enfin, nous exportons notre variable d’application afin qu’elle puisse être importée et utilisée dans d’autres fichiers.

Dans start.js:

const app = require('./app');

const server = app.listen(3000, () => {
  console.log(`Express is running on port ${server.address().port}`);
});

Ici, nous importons l’application Express que nous avons créée dans app.js. (Notez que nous pouvons laisser le .js le nom du fichier dans le require ). Nous demandons ensuite à notre application d’écouter sur le port 3000 les connexions entrantes et d’émettre un message vers le terminal pour indiquer que le serveur est en cours d’exécution.

Et en routes/index.js:

const express = require('express');

const router = express.Router();

router.get("https://www.sitepoint.com/", (req, res) => {
  res.send('It works!');
});

module.exports = router;

Ici, nous importons Express dans notre fichier de routes, puis nous récupérons le routeur. Nous utilisons ensuite le routeur pour répondre à toute demande adressée à l’URL racine (dans ce cas http://localhost:3000) avec un « Ça marche! » message.

Lancez l’application

Enfin, ajoutons un script npm pour que nodemon commence à regarder notre application. Changer la scripts section du package.json fichier pour ressembler à ceci:

"scripts": {
  "watch": "nodemon ./start.js"
},

le scripts propriété du package.json est extrêmement utile, car il vous permet de spécifier des scripts arbitraires à exécuter dans différents scénarios. Cela signifie que vous n’avez pas à taper à plusieurs reprises des commandes longues avec une syntaxe difficile à retenir. Si vous souhaitez en savoir plus sur ce que les scripts npm peuvent faire, lisez Give Grunt the Boot! Un guide d’utilisation de npm comme outil de construction.

Maintenant, tapez npm run watch depuis le terminal et visitez http: // localhost: 3000.

Vous devriez voir « Ça marche! »

Modèles de base avec Pug

Renvoyer une réponse en ligne depuis le gestionnaire d’itinéraire est très bien, mais ce n’est pas très extensible, et c’est là que les moteurs de modèles entrent en jeu. Comme le disent les documents Express:

Un moteur de modèle vous permet d’utiliser des fichiers de modèle statiques dans votre application. Au moment de l’exécution, le moteur de modèle remplace les variables d’un fichier de modèle par des valeurs réelles et transforme le modèle en un fichier HTML envoyé au client.

En pratique, cela signifie que nous pouvons définir des fichiers de modèle et dire à nos itinéraires de les utiliser au lieu d’écrire tout en ligne. Faisons-le maintenant.

Créez un dossier nommé views et dans ce dossier un fichier nommé form.pug. Ajoutez le code suivant à ce nouveau fichier:

form(action="." method="POST")
  label(for="name") Name:
  input(
    type="text"
    id="name"
    name="name"
  )

  label(for="email") Email:
  input(
    type="email"
    id="email"
    name="email"
  )

  input(type="submit" value="Submit")

Comme vous pouvez le déduire de la fin du fichier, nous utiliserons le moteur de création de modèles de pug dans notre application. Pug (anciennement connu sous le nom de Jade) est livré avec sa propre syntaxe sensible à l’indentation pour écrire du HTML dynamique et réutilisable. J’espère que l’exemple ci-dessus est facile à suivre, mais si vous avez des difficultés à comprendre ce qu’il fait, attendez que nous affichions cela dans un navigateur, puis inspectez la source de la page pour voir le balisage qu’il produit.

Si vous souhaitez en savoir un peu plus sur Pug avant de continuer, lisez notre didacticiel Un guide du débutant pour Pug.

Installez Pug et intégrez-le dans l’application Express

Ensuite, nous devons installer pug, l’enregistrant en tant que dépendance:

npm install pug

Configurez ensuite app.js d’utiliser Pug comme moteur de mise en page et de rechercher des modèles dans le views dossier:

const express = require('express');
const path = require('path');
const routes = require('./routes/index');

const app = express();

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use("https://www.sitepoint.com/", routes);

module.exports = app;

Vous remarquerez que nous avons également besoin du module Path natif de Node, qui fournit des utilitaires pour travailler avec les chemins de fichiers et de répertoires. Ce module nous permet de construire le chemin de notre views dossier à l’aide de sa méthode de jointure et de __dirname (qui renvoie le répertoire dans lequel réside le script en cours d’exécution).

Modifier l’itinéraire pour utiliser notre modèle

Enfin, nous devons indiquer à notre itinéraire d’utiliser notre nouveau modèle. Dans routes/index.js:

router.get("https://www.sitepoint.com/", (req, res) => {
  res.render('form');
});

Cela utilise la méthode de rendu sur l’objet de réponse d’Express pour envoyer la vue rendue au client.

Voyons donc si cela a fonctionné. Comme nous utilisons nodemon pour regarder notre application pour les changements, vous devriez simplement pouvoir actualiser votre navigateur et voir notre chef-d’œuvre brutaliste.

Définir un fichier de mise en page pour Pug

Si vous ouvrez votre navigateur et inspectez la source de la page, vous verrez qu’Express n’a envoyé que le code HTML du formulaire: il manque une déclaration doctype sur notre page, ainsi qu’une section tête et corps. Corrigeons cela en créant une mise en page principale pour tous nos modèles à utiliser.

Pour ce faire, créez un layout.pug fichier dans le views dossier et ajoutez le code suivant:

doctype html
html
  head
    title= `${title}`

  body
    h1 My Amazing App

    block content

La première chose à remarquer ici est la ligne commençant title=. Ajouter un signe égal à un attribut est l’une des méthodes utilisées par Pug pour l’interpolation. Vous pouvez en lire plus ici. Nous allons l’utiliser pour transmettre dynamiquement le titre à chaque modèle.

La deuxième chose à noter est la ligne qui commence par le block mot-clé. Dans un modèle, un bloc est simplement un «bloc» de Pug qu’un modèle enfant peut remplacer. Nous verrons comment l’utiliser sous peu, mais si vous souhaitez en savoir plus, lisez cette page sur le site Web de Pug.

Utiliser le fichier de mise en page du modèle enfant

Il ne reste plus qu’à informer notre form.pug modèle qu’il doit utiliser le fichier de mise en page. Pour ce faire, modifiez views/form.pug, ainsi:

extends layout

block content
  form(action="." method="POST")
    label(for="name") Name:
    input(
      type="text"
      id="name"
      name="name"
    )

    label(for="email") Email:
    input(
      type="email"
      id="email"
      name="email"
    )

    input(type="submit" value="Submit")

Et en routes/index.js, nous devons saisir un titre approprié pour que le modèle s’affiche:

router.get("https://www.sitepoint.com/", (req, res) => {
  res.render('form', { title: 'Registration form' });
});

Maintenant, si vous actualisez la page et inspectez la source, les choses devraient être beaucoup mieux.

Traiter les formulaires dans Express

Actuellement, si vous cliquez sur notre formulaire Soumettre , vous serez redirigé vers une page contenant un message: « Impossible de poster / ». En effet, une fois soumis, notre formulaire remet son contenu à /, et nous n’avons pas encore défini d’itinéraire pour gérer cela.

Faisons-le maintenant. Ajoutez ce qui suit à routes/index.js:

router.post("https://www.sitepoint.com/", (req, res) => {
  res.render('form', { title: 'Registration form' });
});

C’est la même chose que notre itinéraire GET, à l’exception du fait que nous utilisons router.post pour répondre à un verbe HTTP différent.

Maintenant, lorsque nous soumettons le formulaire, le message d’erreur disparaîtra et le formulaire devrait simplement être rendu de nouveau.

Gérer la saisie du formulaire

La tâche suivante consiste à récupérer les données que l’utilisateur a soumises via le formulaire. Pour ce faire, nous devons installer un package nommé body-parser, qui rendra les données du formulaire disponibles sur le corps de la demande:

npm install body-parser

Nous devons également indiquer à notre application d’utiliser ce package. Ajoutez donc les éléments suivants à app.js:

const bodyParser = require('body-parser');
...
app.use(bodyParser.urlencoded({ extended: true }));
app.use("https://www.sitepoint.com/", routes);

module.exports = app;

Notez qu’il existe différentes façons de formater les données que vous POSTEZ sur le serveur, et en utilisant la méthode de l’urlencoded de body-parser nous permet de gérer les données envoyées comme application/x-www-form-urlencoded.

Ensuite, nous pouvons essayer d’enregistrer les données soumises sur le terminal. Modifiez le gestionnaire d’itinéraire comme suit:

router.post("https://www.sitepoint.com/", (req, res) => {
  console.log(req.body);
  res.render('form', { title: 'Registration form' });
});

Maintenant, lorsque vous soumettez le formulaire, vous devriez voir quelque chose comme:

{name: 'Jim', email: 'jim@example.com'}

Sortie de formulaire enregistrée sur le terminal

Sortie de formulaire enregistrée sur le terminal

Remarque sur les objets de demande et de réponse

Vous avez maintenant, espérons-le, remarqué le modèle que nous utilisons pour gérer les itinéraires dans Express:

router.METHOD(route, (req, res) => {
  // callback function
});

La fonction de rappel est exécutée chaque fois que quelqu’un visite une URL qui correspond à l’itinéraire qu’il spécifie. Le rappel reçoit un req et res paramètre, où req est un objet plein d’informations qui arrivent (comme les données de formulaire ou les paramètres de requête) et res est un objet plein de méthodes pour renvoyer des données à l’utilisateur. Il y a aussi une option next , ce qui est utile si vous ne voulez pas renvoyer de données ou si vous voulez faire passer la demande pour autre chose à gérer.

Sans aller trop loin dans les mauvaises herbes, c’est un concept connu sous le nom de middleware (en particulier, middleware au niveau du routeur) qui est très important dans Express. Si vous souhaitez en savoir plus sur la façon dont Express utilise le middleware, je vous recommande de lire les documents Express.

Validation de l’entrée de formulaire

Vérifions maintenant que l’utilisateur a rempli nos deux champs. Nous pouvons le faire en utilisant le module express-validator, un middleware qui fournit un certain nombre de méthodes utiles pour la désinfection et la validation des entrées utilisateur.

Vous pouvez l’installer comme ceci:

npm install express-validator

Et nécessitent les fonctions dont nous aurons besoin routes/index.js:

const { check, validationResult } = require('express-validator');

Nous pouvons l’inclure dans notre gestionnaire d’itinéraire comme ceci:

router.post("https://www.sitepoint.com/",
  [
    check('name')
      .isLength({ min: 1 })
      .withMessage('Please enter a name'),
    check('email')
      .isLength({ min: 1 })
      .withMessage('Please enter an email'),
  ],
  (req, res) => {
    ...
  });

Comme vous pouvez le voir, nous utilisons le check méthode pour valider deux propriétés sur req.body – à savoir, name et email. Dans notre cas, il suffit de simplement vérifier que ces propriétés existent (c’est-à-dire qu’elles ont une longueur supérieure à une), mais si vous souhaitez en faire plus, vous pouvez consulter la gamme complète des validateurs ici.

Dans une deuxième étape, nous pouvons appeler la méthode validationResult pour voir si la validation a réussi ou échoué. Si aucune erreur n’est présente, nous pouvons continuer et afficher un message de remerciement pour votre inscription. Sinon, nous devrons retransmettre ces erreurs à notre modèle, afin d’informer l’utilisateur que quelque chose ne va pas.

Et si la validation échoue, nous devrons également passer req.body revenir au modèle, de sorte que toute entrée de formulaire valide ne soit pas réinitialisée:

router.post(
  "https://www.sitepoint.com/",
  [
    ...
  ],
  (req, res) => {
    const errors = validationResult(req);

    if (errors.isEmpty()) {
      res.send('Thank you for your registration!');
    } else {
      res.render('form', {
        title: 'Registration form',
        errors: errors.array(),
        data: req.body,
      });
    }
  }
);

Maintenant, nous devons apporter quelques modifications à notre form.pug modèle. Nous devons d’abord vérifier errors et, si elle est présente, parcourez les erreurs et affichez-les dans une liste:

extends layout

block content
  if errors
    ul
      for error in errors
        li= error.msg
  ...

Si la li= semble étrange, rappelez-vous que Pug effectue une interpolation en suivant le nom de la balise avec un signe égal.

Enfin, nous devons vérifier si un data existe, et si c’est le cas, utilisez-le pour définir les valeurs des champs respectifs. S’il n’existe pas, nous l’initialiserons sur un objet vide, afin que le formulaire s’affiche toujours correctement lorsque vous le chargez pour la première fois. Nous pouvons le faire avec du JavaScript, indiqué dans Pug par un signe moins:

-data = data || {}

Nous référençons ensuite cet attribut pour définir la valeur du champ:

input(
  type="text"
  id="name"
  name="name"
  value=data.name
)

Remarque: dans Pug, tous les attributs sont échappés par défaut. En d’autres termes, les caractères spéciaux sont remplacés par des séquences d’échappement pour empêcher les attaques (telles que les scripts intersites).

Cela nous donne les éléments suivants:

extends layout

block content
  -data = data || {}

  if errors
    ul
      for error in errors
        li= error.msg

  form(action="." method="POST")
    label(for="name") Name:
    input(
      type="text"
      id="name"
      name="name"
      value=data.name
    )

    label(for="email") Email:
    input(
      type="email"
      id="email"
      name="email"
      value=data.email
    )

    input(type="submit" value="Submit")

Maintenant, lorsque vous soumettez une inscription réussie, vous devriez voir un message de remerciement et lorsque vous soumettez le formulaire sans remplir les deux champs, le modèle doit être rendu à nouveau avec un message d’erreur.

Interagir avec une base de données

Nous voulons maintenant connecter notre formulaire à notre base de données, afin de pouvoir enregistrer toutes les données saisies par l’utilisateur. Si vous exécutez Mongo localement, n’oubliez pas de démarrer le serveur avec la commande mongod.

Spécifiez les détails de connexion

Nous aurons besoin d’un endroit pour spécifier nos détails de connexion à la base de données. Pour cela, nous utiliserons un fichier de configuration (qui ne devrait pas être vérifié dans le contrôle de version) et le package dotenv. Dotenv chargera nos détails de connexion à partir du fichier de configuration dans Node’s process.env.

Installez-le comme ceci:

npm install dotenv

Et l’exiger en haut de start.js:

require('dotenv').config();

Ensuite, créez un fichier nommé .env dans la racine du projet (notez que le démarrage d’un nom de fichier avec un point peut le masquer sur certains systèmes d’exploitation) et entrez les détails de votre connexion Mongo sur la première ligne.

Si vous exécutez Mongo localement:

DATABASE=mongodb://localhost:27017/

Si vous utilisez mLabs:

DATABASE=mongodb://:@ds211709.mlab.com:11709/?authSource=

Notez que les installations locales de MongoDB n’ont pas d’utilisateur ou de mot de passe par défaut. C’est certainement quelque chose que vous voudrez changer dans la production, car c’est sinon un risque pour la sécurité.

Connectez-vous à la base de données

Pour établir la connexion à la base de données et effectuer des opérations sur celle-ci, nous utiliserons Mongoose. Mongoose est un ODM (mappeur de document objet) pour MongoDB, et comme vous pouvez le lire sur la page d’accueil du projet:

Mongoose fournit une solution simple basée sur un schéma pour modéliser les données de votre application. Il comprend la conversion de type intégrée, la validation, la création de requêtes, les crochets de logique métier et plus encore, prêts à l’emploi.

Ce que cela signifie en termes réels, c’est qu’il crée diverses abstractions sur Mongo, ce qui facilite l’interaction avec notre base de données et réduit la quantité de passe-partout que nous devons écrire. Si vous souhaitez en savoir plus sur le fonctionnement de Mongo sous le capot, assurez-vous de lire notre Introduction à MongoDB.

Pour installer Mongoose:

npm install mongoose

Ensuite, exigez-le dans start.js:

const mongoose = require('mongoose');

La connexion se fait comme suit:

mongoose.connect(process.env.DATABASE, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

mongoose.connection
  .on('open', () => {
    console.log('Mongoose connection open');
  })
  .on('error', (err) => {
    console.log(`Connection error: ${err.message}`);
  });

Remarquez comment nous utilisons le DATABASE variable que nous avons déclaré dans le .env pour spécifier l’URL de la base de données.

C’est quoi start.js devrait maintenant ressembler à:

require('dotenv').config();
const mongoose = require('mongoose');

mongoose.connect(process.env.DATABASE, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

mongoose.connection
  .on('open', () => {
    console.log('Mongoose connection open');
  })
  .on('error', (err) => {
    console.log(`Connection error: ${err.message}`);
  });

const app = require('./app');
const server = app.listen(3000, () => {
  console.log(`Express is running on port ${server.address().port}`);
});

Lorsque vous enregistrez le fichier, nodemon redémarrera l’application et, si tout se passe bien, vous devriez voir le message « Mongoose connection open ».

Définir un schéma de mangouste

MongoDB pouvez être utilisé comme une base de données lâche, ce qui signifie qu’il n’est pas nécessaire de décrire à l’avance à quoi les données ressembleront. Cependant, nous utilisons Mongoose pour interagir avec lui, et tout dans Mongoose commence par un schéma. Dans Mongoose, chaque schéma correspond à une collection MongoDB et définit la forme des documents au sein de cette collection.

À cette fin, créez un models dossier à la racine du projet, et dans ce dossier, un nouveau fichier nommé Registration.js.

Ajoutez le code suivant à Registration.js:

const mongoose = require('mongoose');

const registrationSchema = new mongoose.Schema({
  name: {
    type: String,
    trim: true,
  },
  email: {
    type: String,
    trim: true,
  },
});

module.exports = mongoose.model('Registration', registrationSchema);

Ici, nous ne faisons que définir un type (car nous avons déjà une validation en place) et utilisons la méthode d’aide à l’ajustement pour supprimer tout espace blanc superflu de l’entrée utilisateur. Nous compilons ensuite un modèle à partir de la définition de schéma et l’exportons pour l’utiliser ailleurs dans notre application.

La dernière pièce de passe-partout est d’exiger le modèle start.js:

...

require('./models/Registration');
const app = require('./app');

const server = app.listen(3000, () => {
  console.log(`Express is running on port ${server.address().port}`);
});

Enregistrer les données dans la base de données

Nous sommes maintenant prêts à enregistrer les données utilisateur dans notre base de données. Commençons par exiger Mongoose et importons notre modèle dans notre routes/index.js fichier:

const express = require('express');
const mongoose = require('mongoose');
const { check, validationResult } = require('express-validator');

const router = express.Router();
const Registration = mongoose.model('Registration');
...

Maintenant, lorsque l’utilisateur publie des données sur le serveur, si la validation réussit, nous pouvons continuer et créer un nouveau Registration objet et essayez de l’enregistrer. Comme l’opération de base de données est une opération asynchrone qui renvoie une promesse, nous pouvons enchaîner un .then() à la fin de celui-ci pour faire face à un insert réussi et un .catch() pour faire face à toute erreur:

if (errors.isEmpty()) {
  const registration = new Registration(req.body);
  registration.save()
    .then(() => { res.send('Thank you for your registration!'); })
    .catch((err) => {
      console.log(err);
      res.send('Sorry! Something went wrong.');
    });
} else {
  ...
}

...

Maintenant, si vous entrez vos coordonnées dans le formulaire d’inscription, elles doivent être conservées dans la base de données. Vous pouvez le vérifier à l’aide de Compass (assurez-vous d’appuyer sur le bouton d’actualisation en haut à gauche s’il est toujours en cours d’exécution).

Utilisation de Compass pour vérifier que nos données ont été enregistrées dans MongoDB

Utilisation de Compass pour vérifier que nos données ont été enregistrées dans MongoDB

Récupérer des données de la base de données

Pour terminer l’application, créons un itinéraire final, qui répertorie toutes nos inscriptions. J’espère que vous devriez maintenant avoir une idée raisonnable du processus.

Ajouter un nouvel itinéraire à routes/index.js, comme suit:

router.get('/registrations', (req, res) => {
  res.render('index', { title: 'Listing registrations' });
});

Cela signifie que nous aurons également besoin d’un modèle de vue correspondant (views/index.pug):

extends layout

block content
  p No registrations yet :(

Maintenant, lorsque vous visitez http: // localhost: 3000 / inscriptions, vous devriez voir un message vous indiquant qu’il n’y a pas d’inscriptions.

Corrigeons cela en récupérant nos enregistrements de la base de données et en les transmettant à la vue. Nous afficherons toujours le message « Aucune inscription pour le moment », mais uniquement s’il n’y en a vraiment pas.

Dans routes/index.js:

router.get('/registrations', (req, res) => {
  Registration.find()
    .then((registrations) => {
      res.render('index', { title: 'Listing registrations', registrations });
    })
    .catch(() => { res.send('Sorry! Something went wrong.'); });
});

Ici, nous utilisons la méthode Mongo Collection # find, qui, si elle est invoquée sans paramètres, renverra tous les enregistrements de la collection. La recherche dans la base de données étant asynchrone, nous attendons qu’elle se termine avant de rendre la vue. Si des enregistrements ont été renvoyés, ils seront transmis au modèle de vue dans le registrations propriété. Si aucun enregistrement n’a été retourné, registrations sera un tableau vide.

Dans views/index.pug, nous pouvons ensuite vérifier la longueur de tout ce qui nous est remis et boucler dessus et afficher les enregistrements à l’écran, ou afficher un message « Aucune inscription »:

extends layout

block content

  if registrations.length
    table
      tr
        th Name
        th Email
      each registration in registrations
        tr
          td= registration.name
          td= registration.email
  else
    p No registrations yet :(

Ajouter une authentification HTTP

La dernière fonctionnalité que nous ajouterons à notre application est l’authentification HTTP, verrouillant la liste des enregistrements réussis des regards indiscrets.

Pour ce faire, nous utiliserons le module http-auth, que nous pouvons installer en utilisant:

npm install http-auth

Ensuite, nous devons l’exiger dans routes/index.js, ainsi que le module Path que nous avons rencontré précédemment:

const path = require('path');
const auth = require('http-auth');

Ensuite, indiquez-lui où trouver le fichier dans lequel nous répertorierons les utilisateurs et les mots de passe (dans ce cas, users.htpasswd à la racine du projet):

const basic = auth.basic({
  file: path.join(__dirname, '../users.htpasswd'),
});

Créez ceci users.htpasswd fichier suivant et ajoutez un nom d’utilisateur et un mot de passe séparés par deux points. Cela peut être en texte brut, mais le module http-auth prend également en charge les mots de passe hachés, vous pouvez donc également exécuter le mot de passe via un service tel que Htpasswd Generator.

Pour moi, le contenu de users.htpasswd ressemble à ça:

jim:$apr1$FhFmamtz$PgXfrNI95HFCuXIm30Q4V0

Cela se traduit par l’utilisateur: jim, mot de passe: password.

Enfin, ajoutez-le à l’itinéraire que vous souhaitez protéger et vous êtes prêt à partir:

router.get('/registrations', auth.connect(basic), (req, res) => {
  ...
});

Servir des actifs statiques dans Express

Donnons à l’application un peu de raffinement et ajoutons du style à l’aide de Bootstrap. Nous pouvons servir des fichiers statiques tels que des images, des fichiers JavaScript et des fichiers CSS dans Express en utilisant la fonction middleware express.static intégrée.

La configuration est simple. Ajoutez simplement la ligne suivante à app.js:

app.use(express.static('public'));

Maintenant, nous pouvons charger des fichiers qui sont dans le public annuaire.

Stylisez l’application avec Bootstrap

Créer un public dans la racine du projet et dans le répertoire public répertoire créer un css annuaire. Téléchargez la version réduite de Bootstrap v4 dans ce répertoire, en vous assurant qu’elle est nommée bootstrap.min.css.

Ensuite, nous devons ajouter du balisage à nos modèles de pug.

Dans layout.pug:

doctype html
html
  head
    title= `${title}`
    link(rel='stylesheet', href="https://www.sitepoint.com/css/bootstrap.min.css")
    link(rel='stylesheet', href='/css/styles.css')

  body
    div.container.listing-reg
      h1 My Amazing App

      block content

Ici, nous incluons deux fichiers de notre précédent css dossier et en ajoutant un div wrapper.

Dans form.pug nous ajoutons quelques noms de classe aux messages d’erreur et aux éléments de formulaire:

extends layout

block content
  -data = data || {}

  if errors
    ul.my-errors
      for error in errors
        li= error.msg

  form(action="." method="POST" class="form-registration")
    label(for="name") Name:
    input(
      type="text"
      id="name"
      name="name"
      class="form-control"
      value=data.name
    )

    label(for="email") Email:
    input(
      type="email"
      id="email"
      name="email"
      class="form-control"
      value=data.email
    )

    input(
      type="submit"
      value="Submit"
      class="btn btn-lg btn-primary btn-block"
    )

Et en index.pug, plus ou moins pareil:

extends layout

block content

  if registrations.length
    table.listing-table.table-dark.table-striped
      tr
        th Name
        th Email
      each registration in registrations
        tr
          td= registration.name
          td= registration.email
  else
    p No registrations yet :(

Enfin, créez un fichier appelé styles.css dans le css dossier et ajoutez les éléments suivants:

body {
  padding: 40px 10px;
  background-color: #eee;
}
.listing-reg h1 {
  text-align: center;
  margin: 0 0 2rem;
}

/* css for registration form and errors*/
.form-registration {
  max-width: 330px;
  padding: 15px;
  margin: 0 auto;
}
.form-registration {
  display: flex;
  flex-wrap: wrap;
}
.form-registration input {
  width: 100%;
  margin: 0px 0 10px;
}
.form-registration .btn {
  flex: 1 0 100%;
}
.my-errors {
  margin: 0 auto;
  padding: 0;
  list-style: none;
  color: #333;
  font-size: 1.2rem;
  display: table;
}
.my-errors li {
  margin: 0 0 1rem;
}
.my-errors li:before {
  content: "! Error : ";
  color: #f00;
  font-weight: bold;
}

/* Styles for listing table */
.listing-table {
  width: 100%;
}
.listing-table th,
.listing-table td {
  padding: 10px;
  border-bottom: 1px solid #666;
}
.listing-table th {
  background: #000;
  color: #fff;
}
.listing-table td:first-child,
.listing-table th:first-child {
  border-right: 1px solid #666;
}

Maintenant, lorsque vous actualisez la page, vous devriez voir toute la gloire de Bootstrap!

Conclusion

J’espère que vous avez apprécié ce didacticiel. Bien que nous n’ayons pas construit le prochain Facebook, j’espère que j’ai quand même pu vous aider à vous lancer dans le monde des applications Web basées sur Node et vous offrir des plats à emporter solides pour votre prochain projet dans le processus.

Bien sûr, il est difficile de tout couvrir dans un seul didacticiel, et il existe de nombreuses façons d’élaborer sur ce que nous avons construit ici. Par exemple, vous pouvez consulter notre article sur le déploiement des applications Node et essayer de le lancer sur Heroku ou maintenant. Vous pouvez également augmenter la fonctionnalité CRUD avec la possibilité de supprimer les enregistrements, ou même d’écrire quelques tests pour tester la fonctionnalité de l’application.

Où que vous alliez, n’hésitez pas à me tirer des questions ou des commentaires sur Twitter.

Inscris-toi à notre newsletter !

Partage cet article avec tes amis !

Share on facebook
Share on google
Share on twitter
Share on linkedin