Fermer

février 26, 2020

Créer une application simple pour débutant avec Node, Bootstrap et MongoDB –


Si vous débutez avec Node.js et que vous souhaitez 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, le monde!" des 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 que, lorsque vous avez terminé, vous avez construit quelque chose agréable et brillant, mais vous avez également relativement peu de points à retenir 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. Ceux-ci incluent le routage, les modèles, le traitement des formulaires, l'interaction avec une base de données et même l'authentification de base.

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

Ce que nous allons construire [19659006] Nous utiliserons Node.js et le cadre Express pour créer un simple formulaire d'inscription avec validation de base, qui conservera 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 commencer le codage, nous allons besoin d'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 du mal à vous installer, veuillez visiter nos forums et demander de l'aide là-bas.

Node.js

De nombreux sites Web vous recommandera de vous rendre sur la page officielle de téléchargement des nœuds et de récupérer les fichiers binaires des nœuds pour 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 vous verraient autrement installer des packages avec des droits d'administrateur.

Si vous avez envie de 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, donc si vous avez besoin d'une mise à jour, veuillez consulter Un guide du débutant pour npm – le Node Package Manager .

MongoDB [19659010] 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 .

La façon la plus rapide de se lancer et de fonctionner 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 si vous rencontrez des problèmes.

Une interface graphique MongoDB

Bien que cela ne soit pas strictement nécessaire pour suivre ce didacticiel, vous aimerez peut-être aussi pour 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 dotés de toutes les fonctionnalités CRUD.

Vérifiez que tout est correctement installé

Pour vérifier que Node et npm sont installés correctement, ouvrez votre terminal et tapez: [19659022] noeud -v

suivi de:

 npm -v

Ceci 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 peut 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 le bouton CONNECT 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 sur Remplissez les champs de connexion individuellement . Sélectionnez Nom d'utilisateur / Mot de passe comme méthode d'authentification, puis remplissez le reste des détails. Enfin, cliquez sur CONNECTER 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 = .

 Boussole MongoDB connectée aux mLabs

Boussole MongoDB connecté à mLabs

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

Initialiser l'application

Une fois tout 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 tapez ce qui suit dans un terminal:

 npm init -y

Cela créera et remplira automatiquement un fichier package.json dans 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.

Install 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 comprennent des éléments tels que la gestion des itinéraires, l'intégration du moteur de modèle et un framework 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.

Alors installons Express . Pour ce faire, exécutez ce qui suit dans votre terminal:

 npm install express

Cela verra Express ajouté à la section dépendances du fichier package.json . Cela signale à quiconque exécute 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 juste avec le développement), alors installez-le en utilisant:

 npm install --save-dev nodemon

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

Créer quelques 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 dossier demo-node-app créez un fichier app.js et un fichier start.js . Créez également un dossier routes avec un fichier index.js à l'intérieur. Une fois que vous avez terminé, les choses devraient ressembler à ceci:

.
├── app.js
├── node_modules
│ └── ...
├── package.json
├── package-lock.json
├── itinéraires
│ └── 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 ('/', routes);

module.exports = app;

Ici, nous importons à la fois le module express et (la valeur d'exportation de) notre fichier routes dans l'application. La fonction nécessite que nous utilisons pour ce faire est une fonction de nœud intégrée qui importe un objet à partir d'un autre fichier ou module. Si vous souhaitez un rappel 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 en utilisant le exprimer la fonction et l'attribuer à une variable app . 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 s'exécute sur le 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 hors du nom de fichier dans la déclaration require .) Nous demandons ensuite à notre application d'écouter sur le port 3000 les connexions entrantes et d'envoyer un message au terminal pour indiquer que le serveur fonctionne.

Et dans routes / index.js :

 const express = require ('express');

const router = express.Router ();

router.get ('/', (req, res) => {
  res.send ('Ça marche!');
});

module.exports = routeur;

Ici, nous importons Express dans notre fichier de routes, puis nous récupérons le routeur. Nous utilisons ensuite le routeur pour répondre à toutes les demandes adressées à l'URL racine (dans ce cas http: // localhost: 3000 ) avec un "Ça marche!"

Lancez l'application

Enfin, ajoutons un script npm pour que nodemon commence à regarder notre application. Modifiez la section scripts du fichier package.json pour qu'elle ressemble à ceci:

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

La propriété scripts du fichier package.json est extrêmement utile, car elle 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! A Guide to Using npm as a Build Tool .

Tapez maintenant npm run watch depuis le terminal et visitez http: // localhost: 3000 .

Vous devriez voir "Ça marche!"

Modèles de base avec Pug

Le renvoi d'une réponse en ligne à partir du gestionnaire d'itinéraire est très bien, mais ce n'est pas très extensible, et c'est là qu'interviennent les moteurs de modèles. Express docs état:

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 à la place d'écrire tout en ligne. Faisons-le maintenant.

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

 formulaire (action = "." Method = "POST")
  label (for = "name") Nom:
  contribution(
    type = "texte"
    id = "nom"
    nom = "nom"
  )

  label (for = "email") Email:
  contribution(
    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 jusqu'à ce que nous le visualisions dans un navigateur, puis inspectez la source de la page pour voir le balisage qu'il produit.

Si vous le souhaitez a pour en savoir un peu plus sur Pug avant de continuer, lisez notre tutoriel Guide du débutant pour Pug .

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

Ensuite, nous devons installer pug , sauvegarde en tant que dépendance:

 npm install pug

Configurez ensuite app.js pour utiliser Pug comme moteur de présentation et pour rechercher des modèles dans le dossier vues :

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

const app = express ();

app.set ('vues', path.join (__ dirname, 'vues'));
app.set («moteur de vue», «pug»);

app.use ('/', routes);

module.exports = app;

Vous remarquerez que nous avons également besoin du module de chemin natif de Node qui fournit des utilitaires pour travailler avec les chemins de fichiers et de répertoires. Ce module nous permet de créer le chemin d'accès à notre dossier vues en utilisant sa méthode de jointure et __ dirname (qui renvoie le répertoire dans lequel réside le script en cours d'exécution).

Modifier la route pour utiliser notre modèle

Enfin, nous devons indiquer à notre route d'utiliser notre nouveau modèle. Dans routes / index.js :

 router.get ('/', (req, res) => {
  res.render ('formulaire');
});

Ceci utilise la méthode de rendu sur l'objet 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 rafraîchir votre navigateur et voir notre chef-d'œuvre brutaliste.

Définissez 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 HTML du formulaire: il manque une déclaration doctype sur notre page, ainsi qu'une section head et body. Corrigeons cela en créant une disposition principale pour tous nos modèles à utiliser.

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

 doctype html
html
  tête
    title = `$ {title}`

  corps
    h1 My Amazing App

    bloquer le contenu

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 savoir plus à ce sujet ici . Nous allons l'utiliser pour passer le titre dynamiquement à chaque modèle.

La deuxième chose à noter est la ligne qui commence par le mot-clé block . 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 .

Utilisez le fichier de mise en page à partir du modèle enfant

Tous il reste à informer notre modèle form.pug qu'il doit utiliser le fichier de mise en page. Pour ce faire, modifiez views / form.pug comme ceci:

 étend la disposition

bloquer le contenu
  formulaire (action = "." method = "POST")
    label (for = "name") Nom:
    contribution(
      type = "texte"
      id = "nom"
      nom = "nom"
    )

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

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

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

 router.get ('/', (req, res) => {
  res.render ('formulaire', {title: 'Formulaire d'inscription'});
});

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

Traitement des formulaires dans Express

Actuellement, si vous appuyez sur le bouton Soumettre de notre formulaire, vous ' ll sera redirigé vers une page avec un message: «Cannot POST /». En effet, une fois soumis, notre formulaire remet son contenu à / et nous n'avons pas encore défini de voie pour gérer cela.

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

 router.post ('/', (req, res) => {
  res.render ('formulaire', {title: 'Formulaire d'inscription'});
});

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

Maintenant, lorsque nous soumettons le formulaire, l'erreur

Gérer l'entrée du formulaire

La tâche suivante consiste à récupérer toutes 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 ce qui suit à app.js :

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

module.exports = app;

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

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

 router.post ('/', (req, res) => {
  console.log (req.body);
  res.render ('formulaire', {title: 'Formulaire d'inscription'});
});

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

 {nom: '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, nous l'espérons, remarqué le modèle nous utilisons pour gérer les routes dans Express:

 router.METHOD (route, (req, res) => {
  // fonction de rappel
});

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 paramètre req et res req est un objet plein d'informations qui arrivent (comme des données de formulaire ou des 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 un paramètre facultatif suivant qui est utile si vous ne voulez pas réellement renvoyer de données, ou si vous voulez faire passer la demande pour autre chose à gérer.

Sans trop profondément 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 .

Validating Form Input

Vérifions maintenant que l'utilisateur a rempli nos deux champs . Nous pouvons le faire en utilisant le module de validation express 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 suit:

 npm install express -validateur

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

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

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

 router.post ('/',
  [
    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 la méthode check 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 renvoyer ces erreurs à notre modèle, afin d'informer l'utilisateur que quelque chose ne va pas.

Et si la validation échoue, nous devrons également renvoyer req.body au modèle, afin que toutes les entrées de formulaire valides ne soient pas réinitialisées:

 router.post (
  '/',
  [
    ...
  ],
  (req, res) => {
    const errors = validationResult (req);

    if (errors.isEmpty ()) {
      res.send ('Merci pour votre inscription!');
    } autre {
      res.render ('form', {
        titre: «Formulaire d'inscription»,
        erreurs: errors.array (),
        données: corps requis,
      });
    }
  }
);

Nous devons maintenant apporter quelques modifications à notre modèle form.pug . Nous devons d'abord vérifier la propriété des erreurs et si elle est présente, parcourir les erreurs et les afficher dans une liste:

 étend la disposition

bloquer le contenu
  si erreurs
    ul
      pour erreur dans les erreurs
        li = error.msg
  ...

Si le li = semble bizarre, 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 attribut data data existe, et si oui, 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 = "texte"
  id = "nom"
  nom = "nom"
  valeur = data.name
)

Remarque: dans Pug, tous les attributs sont échappés par défaut. C'est-à-dire que les caractères spéciaux sont remplacés par des séquences d'échappement pour empêcher les attaques (comme les scripts intersites).

Cela nous donne ce qui suit:

 étend la disposition

bloquer le contenu
  -data = données || {}

  si erreurs
    ul
      pour erreur dans les erreurs
        li = error.msg

  formulaire (action = "." method = "POST")
    label (for = "name") Nom:
    contribution(
      type = "texte"
      id = "nom"
      nom = "nom"
      valeur = data.name
    )

    label (for = "email") Email:
    contribution(
      type = "email"
      id = "email"
      name = "email"
      valeur = 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 restitué 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 les détails de connexion de notre base de données. Pour cela, nous utiliserons un fichier de configuration (qui ne doit pas être vérifié dans le contrôle de version) et le package dotenv . Dotenv chargera nos détails de connexion depuis le fichier de configuration dans le processus Node .

Installez-le comme ceci:

 npm install dotenv

Et l'exige en haut de start.js :

 require ('dotenv'). Config ();

Ensuite, créez un fichier nommé .env à 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 le premier

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é.

Se connecter à la base de données

Pour établir la connexion à la base de données et effectuer des opérations sur celle-ci, nous utiliserons Mangouste . 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 directe basée sur un schéma pour modéliser les données de votre application. Cela inclut la conversion de type intégrée, la validation, la création de requêtes, les crochets de logique métier et plus encore.

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éduire la quantité de passe-partout que nous devons écrire. Si vous souhaitez en savoir plus sur le fonctionnement de Mongo sous le capot, lisez bien notre Introduction à MongoDB .

Pour installer Mongoose:

 npm install mongoose

Ensuite, exigez-le dans start.js :

 const mongoose = require ('mongoose');

La connexion est établie comme suit:

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

mongoose.connection
  .on ('ouvert', () => {
    console.log ('Mongoose connection open');
  })
  .on ('erreur', (err) => {
    console.log (`Erreur de connexion: $ {err.message}`);
  });

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

Voici ce que start.js devrait maintenant ressembler à:

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

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

mongoose.connection
  .on ('ouvert', () => {
    console.log ('Mongoose connection open');
  })
  .on ('erreur', (err) => {
    console.log (`Erreur de connexion: $ {err.message}`);
  });

const app = require ('./ app');
const server = app.listen (3000, () => {
  console.log (`Express s'exécute sur le 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 Mongoose

MongoDB peut ê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 de cette collection.

À cette fin, créez un dossier models dans 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 = nouvelle mangouste.Schema ({
  Nom: {
    type: String,
    garniture: vrai,
  },
  email: {
    type: String,
    garniture: vrai,
  },
});

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'assiette 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 une utilisation ailleurs dans notre application.

La dernière pièce du passe-partout consiste à exiger le modèle dans start.js :

 ...

exiger («./ modèles / enregistrement»);
const app = require ('./ app');

const server = app.listen (3000, () => {
  console.log (`Express s'exécute sur le 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 fichier routes / index.js :

 const express = require ('express');
const mangouste = require ('mangouste');
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 nouvel objet Enregistrement et tenter de l'enregistrer. L'opération de base de données étant une opération asynchrone qui renvoie une promesse, nous pouvons enchaîner un .then () à la fin pour gérer un insert réussi et un .catch () pour traiter les erreurs:

 if (errors.isEmpty ()) {
  const registration = nouvel enregistrement (req.body);
  registration.save ()
    .then (() => {res.send ('Merci pour votre inscription!');})
    .catch ((err) => {
      console.log (err);
      res.send ('Désolé! Quelque chose s'est mal passé.');
    });
} autre {
  ...
}

...

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 vérifier cela à l'aide de Compass (en vous assurant 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

Using Compass to check that our data was saved to MongoDB

Retrieve Data from the Database

To round the app off, let's create a final route, which lists out all of our registrations. Hopefully you should have a reasonable idea of the process by now.

Add a new route to routes/index.jsas follows:

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

This means that we’ll also need a corresponding view template (views/index.pug):

extends layout

block content
  p No registrations yet :(

Now when you visit http://localhost:3000/registrationsyou should see a message telling you that there aren’t any registrations.

Let’s fix that by retrieving our registrations from the database and passing them to the view. We’ll still display the “No registrations yet” message, but only if there really aren’t any.

In 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.'); });
});

Here, we’re using Mongo’s Collection#find methodwhich, if invoked without parameters, will return all of the records in the collection. Because the database lookup is asynchronous, we’re waiting for it to complete before rendering the view. If any records were returned, these will be passed to the view template in the registrations property. If no records were returned, registrations will be an empty array.

In views/index.pugwe can then check the length of whatever we’re handed and either loop over it and output the records to the screen, or display a “No registrations” message:

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 :(

Add HTTP Authentication

The final feature we’ll add to our app is HTTP authenticationlocking down the list of successful registrations from prying eyes.

To do this, we’ll use the http-auth modulewhich we can install using:

npm install http-auth

Next, we need to require it in routes/index.jsalong with the Path module we met earlier:

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

Next, let it know where to find the file in which we’ll list the users and passwords (in this case, users.htpasswd in the project root):

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

Create this users.htpasswd file next and add a username and password separated by a colon. This can be in plain text, but the http-auth module also supports hashed passwords, so you could also run the password through a service such as Htpasswd Generator.

For me, the contents of users.htpasswd looks like this:

jim:$apr1$FhFmamtz$PgXfrNI95HFCuXIm30Q4V0

This translates to user: jimpassword: password.

Finally, add it to the route you wish to protect and you’re good to go:

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

Serve Static Assets in Express

Let’s give the app some polish and add some styling using Bootstrap. We can serve static files such as images, JavaScript files and CSS files in Express using the built-in express.static middleware function.

Setting it up is easy. Just add the following line to app.js:

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

Now we can load files that are in the public directory.

Style the App with Bootstrap

Create a public directory in the project root, and in the public directory create a css directory. Download the minified version of Bootstrap v4 into this directory, ensuring it’s named bootstrap.min.css.

Next, we’ll need to add some markup to our pug templates.

In layout.pug:

doctype html
html
  head
    title= `${title}`
    link(rel='stylesheet', href='/css/bootstrap.min.css')
    link(rel='stylesheet', href='/css/styles.css')

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

      block content

Here, we’re including two files from our previously created css folder and adding a wrapper div.

In form.pug we add some class names to the error messages and the form elements:

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"
    )

And in index.pugmore of the same:

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 :(

Finally, create a file called styles.css in the css folder and add the following:

body {
  padding: 40px 10px;
  background-color: #eee;
}
.listing-reg h1 {
  alignement du texte: centre;
  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;
}

Now when you refresh the page, you should see all of the Bootstrap glory!

Conclusion

I hope you’ve enjoyed this tutorial. While we didn’t build the next Facebook, I hope that I was nonetheless able to help you make a start in the world of Node-based web apps and offer you some solid takeaways for your next project in the process.

Of course, it’s hard to cover everything in one tutorial, and there are lots of ways you could elaborate on what we’ve built here. For example, you could check out our article on deploying Node apps and try your hand at launching it to Heroku or now. Alternatively, you might augment the CRUD functionality with the ability to delete registrations, or even write a couple of tests to test the app’s functionality.

Wherever you go from here, feel free to shoot me questions or comments on Twitter.






Source link