Fermer

mai 29, 2018

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


Si vous ne faites que commencer avec Node.js et que vous voulez vous lancer dans la création d'une application Web, les choses peuvent souvent devenir un peu écrasantes. Une fois que vous avez dépassé les tutoriels "Bonjour, monde!", Une grande partie du contenu vous propose de copier-coller du code, avec peu ou pas d'explications sur ce que vous faites ou pourquoi.

Quand vous avez fini, vous avez construit quelque chose de sympa et brillant, mais vous avez aussi relativement peu de choses à retenir que vous pouvez appliquer à votre prochain projet.

Dans ce tutoriel, je vais adopter une approche légèrement différente. En partant de zéro, je vais vous montrer comment créer une application web simple en utilisant Node.js, mais au lieu de me concentrer sur le résultat final, je vais me concentrer sur une série de choses que vous pourriez rencontrer lors de la construction. une application du monde réel. Cela inclut le routage, la création de 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 cherchez, . Il sera, cependant, approprié pour ceux qui se sentent raisonnablement confiants avec le langage Javascript, et qui cherchent à faire leurs premiers pas dans Node.js.

Ce que nous construirons

Nous utiliserons Node.js et le framework Express pour construire un formulaire d'inscription simple avec validation de base, qui conserve ses données dans une base de données MongoDB . Nous allons ajouter une vue pour répertorier une inscription réussie, que nous protégerons avec une authentification HTTP de base, et nous utiliserons Bootstrap pour ajouter du style. Le tutoriel est structuré pour que vous puissiez suivre étape par étape. Cependant, si vous voulez aller de l'avant et voir le résultat final, le code de ce tutoriel est également disponible sur GitHub .

Configuration de base

Avant de pouvoir commencer à coder, nous allons besoin d'avoir Node, NPM et MongoDB installés sur nos machines. Je ne vais pas entrer dans les détails sur les différentes instructions d'installation, mais si vous avez des problèmes pour installer, laissez un commentaire ci-dessous, ou visitez nos forums et demandez de l'aide là-bas.

Noeud. js

De nombreux sites Web vous recommanderont de vous diriger vers la page officielle de téléchargement de nœuds et de récupérer les fichiers binaires de votre système. Alors que cela fonctionne, je suggère que vous utilisiez un gestionnaire de version à la place. C'est 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 divers avantages, par exemple, il supprime les problèmes d'autorisation potentiels qui vous empêcheraient d'installer des paquets avec des droits d'administrateur.

Si vous avez envie d'utiliser le gestionnaire de versions, consultez notre astuce: Installer Plusieurs versions de Node.js utilisant nvm . Sinon, récupérez les binaires appropriés pour votre système à partir du lien ci-dessus et installez ceux-ci.

npm

npm est un gestionnaire de paquets JavaScript livré avec Node, donc aucune installation supplémentaire n'est nécessaire ici. Nous allons utiliser assez largement npm tout au long de ce tutoriel, donc si vous avez besoin d'un rafraîchissement, veuillez consulter: Guide du débutant sur npm – le gestionnaire de paquetages de nœuds .

MongoDB [19659010] MongoDB est une base de données de documents qui stocke des données dans des documents flexibles de type JSON.

Le moyen le plus rapide de se lancer avec Mongo est d'utiliser un service tel que mLabs. Ils ont un plan de sandbox gratuit qui fournit une base de données unique avec 496 Mo de stockage en cours d'exécution 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 être la meilleure option, veuillez consulter leur guide de démarrage rapide .

Vous pouvez également installer Mongo localement. Pour ce faire, rendez-vous sur la page de téléchargement officielle et téléchargez la version correcte du serveur de communauté pour votre système d'exploitation. Il y a un lien vers des instructions d'installation détaillées, spécifiques à l'OS, 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 tutoriel, 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 la fonctionnalité CRUD complète.

Au moment de la rédaction, vous devrez remplir vos informations pour télécharger Compass, mais vous n'aurez pas besoin de créez un compte.

Vérifiez que tout est correctement installé

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

 node -v

suivi de:

 npm -v

Cela affichera le numéro de version de chaque programme ( 8.9.4 et 5.6.0 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 ( 3.6.2 au moment de l'écriture).

Vérifier la connexion à la base de données avec 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 au serveur de base de données.

 MongoDB Compass connecté à localhost: 27107

MongoDB Compass connecté à localhost

Notez que les bases de données admin et local sont créées 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 copiez les détails de connexion dans le presse-papiers. Cela devrait être sous la forme:

 mongodb: // :  @ ds251827.mlab.com: 51827 / 

Lorsque vous ouvrez Compass, il vous informe qu'il a détecté une chaîne de connexion MongoDB et vous demande si vous souhaitez l'utiliser pour remplir le formulaire. Cliquez sur Oui en notant que vous devrez peut-être ajuster manuellement le nom d'utilisateur et le mot de passe. Après cela, cliquez sur CONNECTER et vous devriez partir pour les courses

 MongoDB Boussole connectée à mLabs

MongoDB Boussole connectée à mLabs [19659003] Notez que j'ai appelé ma base de données sp-node-article . Vous pouvez appeler le vôtre ce que vous voulez.

Initialiser l'application

Avec tout ce que vous avez configuré correctement, la première chose à 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 pour créer plusieurs scripts npm ce qui facilitera notre processus de développement.

Installer Express

Express est un framework 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 routes, l'intégration du moteur de gabarit et un framework de middleware, ce qui nous permet d'effectuer des tâches supplémentaires sur les objets de requête et de réponse. Il n'y a rien que vous puissiez faire dans Express que vous ne pourriez pas faire en Node.js, mais en utilisant Express, nous n'avons pas besoin de réinventer la roue et de réduire la plaque passante.

Alors installons Express [Listlist5listlist55list5listlist55list55<br>5listlistlist55listlist5list5listlist55Pourcefaireexécutezcequisuitdansvotreterminal:

 npm install --save express

En passant l'option - save à la commande npm install Express sera ajouté à la section dépendances du package.json fichier. Cela signale à toute personne exécutant notre code que Express est un paquet dont notre application a besoin pour fonctionner correctement.

Installer nodemon

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

 npm install --save-dev nodemon

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

Créer des fichiers initiaux

Nous en avons presque fini avec 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── package.json
├── itinéraires
Index └── index.js
└── start.js

Maintenant, ajoutons du code à ces fichiers.

Dans app.js :

 const exprime = 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 de routes dans l'application. La fonction nécessite que nous utilisons pour faire ceci est une fonction de nœud intégrée qui importe un objet d'un autre fichier ou module. Si vous souhaitez un rappel sur l'importation et l'exportation de modules, lisez Présentation du module.exports et des exportations dans Node.js .

Ensuite, nous créons une nouvelle application Express en utilisant le exprimez la fonction et attribuez-la à une variable d'application . Nous indiquons ensuite à l'application que, chaque fois qu'elle reçoit une requête de n'importe quelle 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

start.js :

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

serveur const = 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 sur le nom de fichier dans require ] déclaration). Nous disons alors à notre application d'écouter sur le port 3000 pour les connexions entrantes et de transmettre un message au terminal pour indiquer que le serveur est en cours d'exécution.

Et dans routes / index.js :

 const express = require ('express');

routeur const = express.Router ();

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

module.exports = routeur;

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

Coup d'envoi de l'application

] Enfin, ajoutons un script npm pour que nodemon commence à regarder notre application. Modifiez la section scripts du fichier package.json pour ressembler à 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 besoin de taper à plusieurs reprises des commandes longues avec une syntaxe difficile à mémoriser. Si vous souhaitez en savoir plus sur ce que les scripts npm peuvent faire, lisez Give Grunt the Boot! Guide sur l'utilisation de npm en tant qu'outil de compilation .

Maintenant, tapez npm exécutez la surveillance depuis le terminal et visitez http: // localhost: 3000 .

Vous devriez voir "Ça marche!"

Templating Basic avec Pug

Retourner 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à qu'interviennent les moteurs de templates. Docs exprès état:

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

En pratique, cela signifie que nous pouvons définir des fichiers modèles 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 = "nom") Nom:
  contribution(
    type = "texte"
    id = "nom"
    name = "nom"
  )

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

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

Comme vous pouvez le déduire de la fin du fichier, nous utiliserons le pug templating engine 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. Heureusement, l'exemple ci-dessus est facile à suivre, mais si vous avez des difficultés à comprendre ce qu'il fait, attendez que nous l'ayons vu dans un navigateur, puis inspectez la source de la page pour voir le balisage qu'elle produit.

un rappel sur ce que sont les templates JavaScript et / ou les moteurs de templates, et quand vous devriez les utiliser, lisez Une vue d'ensemble des moteurs de template JavaScript

Installer Pug et l'intégrer dans l'application Express

Ensuite, nous aurons besoin d'installer pug, en l'enregistrant comme une dépendance:

 npm i --save pug

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

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

const app = express ();

app.set ('views', path.join (__ dirname, 'views'));
app.set ('view engine', '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 construire le chemin vers notre dossier views en utilisant sa méthode de jointure et __ dirname (qui retourne 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 pour utiliser notre nouveau modèle. Dans routes / index.js :

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

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 le roquet

Si vous ouvrez votre navigateur et inspectez la source de la page , vous verrez qu'Express n'a envoyé que le HTML pour le formulaire: il manque à notre page une déclaration de type doc, ainsi qu'une section head et body. Corrigeons cela en créant une maquette pour tous nos modèles à utiliser.

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

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

  corps
    h1 Mon application incroyable

    bloquer le contenu

La première chose à remarquer ici est la ligne commençant title = . L'ajout d'un signe égal à un attribut est l'une des méthodes que Pug utilise pour l'interpolation. Vous pouvez en lire plus à ce sujet ici . Nous allons l'utiliser pour transmettre le titre dynamiquement à chaque modèle.

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

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

ce qui reste à faire est d'informer notre modèle form.pug qu'il doit utiliser le fichier layout. Pour ce faire, modifiez views / form.pug comme suit:

 extends layout

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

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

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

Et dans routes / index.js nous devons passer un titre approprié pour le gabarit à afficher:

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

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 le bouton Soumettre de notre formulaire, ll sera redirigé vers une page avec un message: "Can not POST /". Ceci est dû au fait que notre formulaire POSTUE son contenu à / et que nous n'avons pas encore défini de route pour le faire.

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

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

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

Maintenant, quand nous soumettons le formulaire, l'erreur le message sera parti et le formulaire devrait simplement être rendu à nouveau.

Handle Form Input

La tâche suivante consiste à récupérer toutes les données que l'utilisateur a soumises via le formulaire. Pour ce faire, nous devrons installer un paquet nommé body-parser qui rendra les données de formulaire disponibles sur le corps de la requête:

 npm install --save body-parser

Nous devrons aussi dire à notre application d'utiliser ce paquet, donc ajoutez 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 plusieurs façons de formater les données que vous POST sur le serveur, et en utilisant la méthode urlencoded de body-parser, nous pouvons gérer les données envoyées sous application / x-www-form- urlencoded .

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

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

Maintenant, quand 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 requête et de réponse

Vous avez peut-être déjà remarqué le modèle utiliser 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 spécifié. Le rappel reçoit un paramètre req et res req est un objet plein d'informations entrantes (telles que 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 existe également un paramètre facultatif suivant qui est utile si vous ne voulez pas renvoyer de données, ou si vous voulez passer la demande à autre chose pour gérer autre chose.

Sans être trop profond dans les mauvaises herbes, c'est un concept connu sous le nom de middleware (spécifiquement, intergiciel de niveau 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 docs Express

Validating Form Input

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 --save

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

 const {corps, validationRésultat} = require ('express-validator / check');

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

 router.post ('/',
  [
    body('name')
      .isLength({ min: 1 })
      .withMessage('Please enter a name'),
    body('email')
      .isLength({ min: 1 })
      .withMessage('Please enter an email'),
  ],
  (req, res) => {
    ...
  }
)

Comme vous pouvez le voir, nous utilisons la méthode du corps pour valider deux propriétés sur req.body - à savoir, name et email . Dans notre cas, il suffit de vérifier que ces propriétés existent (c'est-à-dire qu'elles ont une longueur supérieure à un), mais express-validator offre une foule d'autres méthodes que vous pouvez lire sur la page d'accueil du projet

Dans un deuxième temps, 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 aller de l'avant et afficher un message «Merci de vous inscrire». 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 passer req.body au modèle, de sorte 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 ('formulaire', {
        titre: "Formulaire d'inscription",
        erreurs: errors.array (),
        list list list list list 5 list list list list 5 list list list 5 list list 5 list list 5 5 list 5 5 list 5 5 list 5 5 5
      });
    }
  }
)

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

 étend la mise en page

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

Si le li = semble bizarre, rappelez-vous que carg fait une interpolation en suivant le nom du tag avec un signe égal.

Enfin, nous devons vérifier si un attribut 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 à un objet vide, de sorte que le formulaire s'affichera correctement lorsque vous le chargerez pour la première fois. Nous pouvons le faire avec du JavaScript, noté 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"
  name = "nom"
  value = data.name
)

Cela nous donne ce qui suit:

 étend la mise en page

bloquer le contenu
  list 5 5 list 5 5 5 list 21 5 5 5 list list 5 5 5 5 list 5 list 5 5 21 5 list 5 list 5 5 5 5 {}

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

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

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

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

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 devrait être re-rendu avec un message d'erreur.

Interagir avec un Base de données

Nous voulons maintenant accrocher notre formulaire à notre base de données, afin que nous puissions sauvegarder toutes les données que l'utilisateur entre. Si vous exécutez Mongo localement, n'oubliez pas de démarrer le serveur avec la commande mongod .

Spécifiez les détails de la connexion

Nous aurons besoin d'un emplacement pour spécifier les détails de connexion à la base de données. Pour cela, nous allons utiliser un fichier de configuration (que ne devrait pas être vérifié dans le contrôle de version) et le paquet dotenv . Dotenv chargera nos détails de connexion à partir du fichier de configuration dans process.env de Node .

Installez-le comme ceci:

 npm install dotenv --save

Et l'exige 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 vos détails de connexion Mongo le premier line.

Si vous exécutez Mongo localement:

 DATABASE = mongodb: // localhost: 27017 / node-demo-application

Si vous utilisez mLabs:

 mongodb: // :  @ ds251827.mlab.com: 51827 / 

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 en production, car c'est un risque de sécurité.

Connexion à la base de données

Pour établir la connexion à la base de données et y effectuer des opérations, nous utiliserons Mangouste . Mongoose est un ORM 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 vos données d'application. Cela inclut le lancement de type intégré, la validation, la création de requêtes, les crochets de logique métier et bien plus encore.

Concrètement, cela crée différentes abstractions sur Mongo, ce qui facilite l'interaction avec notre base de données. réduire la quantité de passe-partout que nous devons écrire. Si vous souhaitez en savoir plus sur le fonctionnement de Mongo, lisez notre Introduction à MongoDB .

Pour installer Mongoose:

 npm install --save mongoose

Puis, l'exiger dans start.js :

 const mongoose = require ('mongoose');

La connexion est faite comme suit:

 mongoose.connect (process.env.DATABASE, {useMongoClient: true});
mongoose.Promise = global.Promise;
mongoose.connection
  .on ('connected', () => {
    console.log (`Connexion Mongoose ouverte sur $ {process.env.DATABASE}`);
  })
  .on ('erreur', (erreur) => {
    console.log (`Erreur de connexion: $ {err.message}`);
  });

Notez 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. Nous demandons également à Mongo d'utiliser ES6 Promises (ce qui est nécessaire car les interactions de la base de données sont asynchrones), car sa propre bibliothèque de promesses par défaut est obsolète.

Voici à quoi devrait ressembler start.js :

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

mongoose.connect (process.env.DATABASE, {useMongoClient: true});
mongoose.Promise = global.Promise;
mongoose.connection
  .on ('connected', () => {
    console.log (`Connexion Mongoose ouverte sur $ {process.env.DATABASE}`);
  })
  .on ('erreur', (erreur) => {
    console.log (`Erreur de connexion: $ {err.message}`);
  });

const app = require ('./ app');
serveur const = app.listen (3000, () => {
  console.log (`Express s'exécute sur le port $ {server.address (). port}`);
});

Lorsque vous enregistrez le fichier, nodemon redémarre l'application et, si tout s'est bien passé, vous devriez voir quelque chose comme:

 Connexion Mongoose ouverte sur mongodb: // localhost: 27017 / node-demo-application

Définir un schéma Mongoose

MongoDB peut être utilisé comme une base de données libre, ce qui signifie qu'il n'est pas nécessaire de décrire à quoi ressembleront les données à l'avance. Cependant, dès la sortie de la boîte, il fonctionne en mode strict, ce qui signifie qu'il vous permettra seulement d'enregistrer des données qu'il connaît à l'avance. Comme nous utiliserons le mode strict, nous devrons définir la forme de nos données en utilisant un schéma . Les schémas vous permettent de définir les champs stockés dans chaque document avec leur type, les exigences de validation et les valeurs par défaut.

Pour cela, créez un dossier models dans la racine du projet, et dans ce dossier, un nouveau fichier nommé Registration.js .

Ajouter le code suivant à Registration.js :

 const mongoose = require ('mongoose');

const registrationSchema = new mongoose.Schema ({
  prénom: {
    type: chaîne,
    couper: vrai,
  },
  email: {
    type: chaîne,
    couper: 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 à la coupe pour supprimer tout espace blanc superflu de l'entrée de l'utilisateur. Nous avons ensuite compiler un modèle à partir de la définition du schéma, et l'exporter pour une utilisation ailleurs dans notre application.

Le dernier morceau de la règle standard est d'exiger le modèle dans start.js :

 ...

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

serveur const = 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 importer notre modèle dans notre fichier routes / index.js :

 const express = require ('express');
const mongoose = require ('mongoose');
const {body, validationResult} = require ('exprès-validateur / contrôle');

routeur const = express.Router ();
const Enregistrement = mongoose.model ('Enregistrement');
...

Maintenant, lorsque l'utilisateur publie des données sur le serveur, si la validation réussit, nous pouvons créer un nouvel objet Registration et tenter de le sauvegarder. Comme l'opération de base de données est une opération asynchrone qui renvoie une promesse, nous pouvons enchaîner un .then () sur la fin de celui-ci pour traiter un insert réussi et un .catch () pour gérer les erreurs:

 if (errors.isEmpty ()) {
  const registration = new Enregistrement (req.body);
  registration.save ()
    .then (() => {res.send ('Merci pour votre inscription!');})
    .catch (() => {res.send ('Désolé, quelque chose s'est mal passé.');});
} autre {
  ...
}

...

Maintenant, si vous entrez vos coordonnées dans le formulaire d'inscription, elles devraient être conservées dans la base de données. You can check this using Compass (making sure to hit the refresh button in the top left if it’s still running).

Using Compass to check that our data was saved to 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
  autre
    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 --save 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 Twitter 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
  tête
    title= `${title}`
    link(rel='stylesheet', href='/css/bootstrap.min.css')
    link(rel='stylesheet', href='/css/styles.css')

  corps
    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
  autre
    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 {
  text-align: 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 {
  rembourrage: 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 get your feet wet 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, I’d be glad to hear any questions or comments below.




Source link