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
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: //
.
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
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
où 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).
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.js
as 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.pug
we 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.js
along 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: jim
password: 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.pug
more 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