Dans ce tutoriel, je vais vous montrer comment implémenter une application de chat en temps réel avec Node.js, Socket.IO et MongoDB, puis nous déploierons cette application sur Modulus ensemble.
Tout d'abord, laissez-moi vous montrer le look final de l'application que nous aurons à la fin de l'article.
Node.js sera le noyau de l'application, avec Express comme MVC, MongoDB pour la base de données et Socket.IO pour la communication en temps réel. Lorsque nous aurons terminé, nous déploierons notre application sur Modulus. La partie MongoDB existe réellement à l'intérieur de Modulus.
1. Scénario
- John veut utiliser notre application et l'ouvre dans le navigateur.
- Sur la première page, il sélectionne un surnom à utiliser pendant le chat et se connecte au chat.
- Dans la zone de texte, il écrit quelque chose et appuie sur Entrée.
- Le texte est envoyé à un service RESTful (Express) et ce texte est écrit dans MongoDB.
- Avant d'écrire dans MongoDB, le même texte sera diffusé aux utilisateurs actuellement connectés à l'application de chat.
Comme vous pouvez le voir, il s'agit d'une application très simple, mais elle couvre presque tout pour une application Web. Il n'y a pas de système de canal dans cette application, mais vous pouvez bifurquer le code source et implémenter le module de canal pour vous entraîner.
2. Conception de projet à partir de zéro
Je vais d'abord essayer d'expliquer les petits morceaux du projet et de les combiner à la fin. Je vais commencer de l'arrière vers l'avant. Alors, commençons par les objets de domaine (modèles MongoDB).
2.1. Modèle
Pour l'abstraction de la base de données, nous utiliserons Mongoose. Dans ce projet, nous n'avons qu'un seul modèle appelé Message
. Ce modèle de message ne contient que du text
, createDate
, et author
User
, car nous n'implémenterons pas complètement un système d'enregistrement/de connexion des utilisateurs. Il y aura une simple page fournissant un surnom, et ce surnom sera enregistré dans un cookie. Ceci sera utilisé dans le Message
modèle sous forme de texte dans le author
domaine. Vous pouvez voir un exemple de modèle JSON ci-dessous :
{ text: "Hi, is there any Full Stack Developer here?" author: "john_the_full_stack", createDate: "2015.05.15" }
Afin de créer des documents comme celui-ci, vous pouvez implémenter un modèle en utilisant les fonctions Mongoose ci-dessous :
var mongoose = require('mongoose') var Message = new mongoose.Schema({ author: String, message: String, createDate: { type: Date, default: Date.now } }); mongoose.model('Message', Message)
Importez simplement le module Mongoose, définissez votre modèle avec ses champs et attributs de champ au format JSON, et créez un modèle avec le nom Message
. Ce modèle sera inclus dans les pages que vous souhaitez utiliser.
Peut-être avez-vous une question sur la raison pour laquelle nous stockons le message dans la base de données, alors que nous diffusons déjà ce message à l'utilisateur dans le même canal. Il est vrai que vous n'êtes pas obligé de stocker les messages de chat, mais je voulais juste expliquer la couche d'intégration de la base de données. Quoi qu'il en soit, nous utiliserons ce modèle dans notre projet à l'intérieur des contrôleurs. Contrôleurs ?
2.2. Contrôleur
Comme je l'ai dit plus tôt, nous utiliserons Express pour la partie MVC. Et C
représente ici le Controller
. Pour nos projets, il n'y aura que deux points de terminaison pour la messagerie. L'un d'eux sert à charger les messages de chat récents, et le second à gérer les messages de chat envoyés pour les stocker dans la base de données, puis les diffuser sur le canal.
..... app.get('/chat', function(req, res){ res.sendFile(__dirname + '/index.html'); }); app.get('/login', function(req, res){ res.sendFile(__dirname + '/login.html'); }); app.post('/messages', function(req, res, next) { var message = req.body.message; var author = req.body.author; var messageModel = new Message(); messageModel.author = author; messageModel.message = message; messageModel.save(function (err, result) { if (!err) { Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) { io.emit("message", messages); }); res.send("Message Sent!"); } else { res.send("Technical error occurred!"); } }); }); app.get('/messages', function(req, res, next) { Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) { res.json(messages); }); }); .....
Les premier et deuxième contrôleurs servent uniquement à servir des fichiers HTML statiques pour les pages de chat et de connexion. Le troisième est pour gérer la demande de publication au /messages
point de terminaison pour la création de nouveaux messages. Dans ce contrôleur, tout d'abord le corps de la requête est converti en modèle Message, puis ce modèle est enregistré dans la base de données à l'aide de la fonction Mongoose save
.
Je ne plongerai pas beaucoup dans Mongoose - vous pouvez consulter la documentation pour plus de détails. Vous pouvez fournir une fonction de rappel pour la fonction de sauvegarde afin de vérifier s'il y a un problème ou non. Si l'opération réussit, nous avons récupéré les cinq derniers enregistrements triés par ordre décroissant de createDate
, et ont diffusé cinq messages aux clients du canal.
Ok, nous avons terminé MC
. Passons à la View
partie.
2.3. Afficher
En général, un moteur de modèle comme Jade, EJS, Handlebars, etc., peut être utilisé dans Express. Cependant, nous n'avons qu'une seule page, et c'est un message de chat, donc je vais le servir de manière statique. En fait, comme je l'ai dit plus haut, il existe deux autres contrôleurs pour servir cette page HTML statique. Vous pouvez voir ce qui suit pour servir une page HTML statique.
app.get('/chat', function(req, res){ res.sendFile(__dirname + '/index.html'); }); app.get('/login', function(req, res){ res.sendFile(__dirname + '/login.html'); });
Ce point de terminaison sert simplement index.html et login.html en utilisant res.sendFile
. Les deux index.html et login.html sont dans le même dossier que server.js, c'est pourquoi nous avons utilisé __dirname
avant le nom du fichier HTML.
2.4. Front-End
Dans la page d'accueil, j'ai utilisé Bootstrap et il n'est pas nécessaire d'expliquer comment j'ai réussi à le faire. Simplement, j'ai lié une fonction à une zone de texte, et chaque fois que vous appuyez sur Entrée touche ou Envoyer bouton, le message sera envoyé au service back-end.
Cette page a également un fichier js requis de Socket.IO pour écouter le canal appelé message
. Le module Socket.IO est déjà importé dans le back-end, et lorsque vous utilisez ce module côté serveur, il ajoute automatiquement un point de terminaison pour servir le fichier Socket.IO js, mais nous utilisons celui qui est servi à partir de cdn <script src="//cdn.socket.io/socket.io-1.3.5.js"></script>
. Chaque fois qu'un nouveau message arrive sur ce canal, il sera automatiquement détecté et la liste des messages sera actualisée avec les cinq derniers messages.
<script> var socket = io(); socket.on("message", function (messages) { refreshMessages(messages); }); function refreshMessages(messages) { $(".media-list").html(""); $.each(messages.reverse(), function(i, message) { $(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div class="media-body">' + message.message + '<br/><small class="text-muted">' + message.author + ' | ' + message.createDate + '</small><hr/></div></div></div></li>'); }); } $(function(){ if (typeof $.cookie("realtime-chat-nickname") === 'undefined') { window.location = "/login" } else { $.get("/messages", function (messages) { refreshMessages(messages) }); $("#sendMessage").on("click", function() { sendMessage() }); $('#messageText').keyup(function(e){ if(e.keyCode == 13) { sendMessage(); } }); } function sendMessage() { $container = $('.media-list'); $container[0].scrollTop = $container[0].scrollHeight; var message = $("#messageText").val(); var author = $.cookie("realtime-chat-nickname"); $.post( "/messages", {message: message, author: author}, function( data ) { $("#messageText").val("") }); $container.animate({ scrollTop: $container[0].scrollHeight }, "slow"); } }) </script>
Il y a une autre vérification dans le code ci-dessus :la partie cookie. Si vous n'avez pas choisi de pseudonyme pour le chat, cela signifie que le cookie n'est pas défini pour le pseudonyme et vous serez automatiquement redirigé vers la page de connexion.
Sinon, les cinq derniers messages seront récupérés par un simple appel Ajax au /messages
point final. De la même manière, chaque fois que vous cliquez sur Envoyer ou appuyez sur Entrée clé, le message texte sera extrait de la zone de texte et le surnom sera extrait du cookie, et ces valeurs seront envoyées au serveur avec une demande de publication. Il n'y a pas de vérification stricte du surnom ici, car je voulais me concentrer sur la partie temps réel, pas sur la partie authentification de l'utilisateur.
Comme vous pouvez le voir, la structure globale du projet est très simple. Venons-en à la partie déploiement. Comme je l'ai dit plus tôt, nous utiliserons Modulus, l'un des meilleurs PaaS pour déployer, faire évoluer et surveiller votre application dans le langage de votre choix.
3. Déploiement
3.1. Prérequis
La première chose qui me vient à l'esprit est de vous montrer comment déployer, mais pour un déploiement réussi, nous avons besoin d'une base de données fonctionnelle. Voyons comment créer une base de données sur Modulus, puis effectuer le déploiement.
Accédez au tableau de bord Modulus après avoir créé un compte. Cliquez sur Bases de données sur la gauche, puis cliquez sur Créer une base de données.
Remplissez les champs obligatoires dans le formulaire contextuel comme ci-dessous.
Lorsque vous remplissez les champs obligatoires et cliquez sur Créer, il créera une base de données MongoDB pour vous et vous verrez l'URL de votre base de données à l'écran. Nous utiliserons MONGO URI , alors copiez cet URI.
Dans notre projet, l'URI Mongo est extrait de la variable d'environnement MONGO_URI
, et vous devez définir cette variable d'environnement dans le tableau de bord. Accédez au tableau de bord, cliquez sur Projets menu, sélectionnez votre projet dans la liste, puis cliquez sur Administration dans le menu de gauche. Dans cette page, vous verrez la section des variables d'environnement lorsque vous faites défiler la page, comme indiqué ci-dessous.
Vous pouvez effectuer un déploiement sur Modulus de deux manières :
- télécharger le fichier ZIP du projet à l'aide du tableau de bord
- déploiement à partir de la ligne de commande à l'aide de la CLI Modulus
Je vais continuer avec l'option de ligne de commande, car l'autre est facile à faire. Tout d'abord, installez Modulus CLI :
npm install -g modulus
Accédez à votre dossier de projet et exécutez la commande suivante pour vous connecter à Modulus.
modulus login
Lorsque vous exécutez la commande ci-dessus, vous serez invité à saisir un nom d'utilisateur et un mot de passe :
Si vous avez créé un compte à l'aide de GitHub, vous pouvez utiliser le --github
option.
modulus login --github
Vous êtes maintenant connecté à Modulus et il est temps de créer un projet. Utilisez la commande suivante pour créer un projet :
modulus project create "Realtime Chat"
Lorsque vous exécutez cette fonction, le temps d'exécution vous sera demandé. Sélectionnez la première option, qui est Node.js, et la seconde vous sera demandée pour la taille du servo, et vous pouvez la conserver par défaut.
Nous avons créé un projet, et cette fois nous allons déployer notre projet actuel sur Modulus. Exécutez la commande suivante pour envoyer le projet en cours au Chat en temps réel projet du côté du module.
modulus deploy
Il déploiera votre projet et vous obtiendrez l'URL de votre projet en cours d'exécution à la fin du message de déploiement réussi :
Realtime Chat running at realtime-chat-46792.onmodulus.net
Comme vous pouvez le constater, le déploiement vers Modulus est très simple !
Modulus CLI a des commandes très utiles à utiliser lors du déploiement de votre projet ou lors de l'exécution. Par exemple, pour suivre les journaux de votre projet en cours d'exécution, vous pouvez utiliser modulus project logs tail
, pour créer une base de données MongoDB, utilisez modulus mongo create <db-name>
, pour définir une variable d'environnement, utilisez modulus env set <key> <value>
, etc. Vous pouvez voir une liste complète des commandes en utilisant l'aide de Modulus.