Bonjour, Habr!
Il était une fois, nous avons publié un
projet pilote
sur la pile MEAN (Mongo, Express, Angular, Node), qui ne nous a généralement pas déçus, cependant, nous avons décidé de ne pas faire d'impressions et de mises à jour supplémentaires à l'époque - contrairement à Manning, qui a
mis à jour ce livre. . Néanmoins, nous continuons à chercher dans cette direction et aujourd'hui, nous aimerions vous parler de la pile MERN associée, où React est situé sur le client, pas Angular. La
parole est donnée à
Tim Smith .

Attention: tout le code de cet article est
ici .
Dans ce guide de pile MERN, nous écrirons un blog simple utilisant React.js, Node.js, Express.js et MongoDB pour étendre notre arsenal de pile complète.
Qu'est-ce qu'une pile?
Peut-être que la première chose à discuter est l'idée d'une "pile" en tant que telle. Il existe de nombreuses piles différentes, et toutes ne sont que des chemins différents pour atteindre le même objectif. En créant une application full-stack, nous fournissons la partie client avec laquelle l'utilisateur va interagir, et la même partie client assurera la médiation du travail avec le serveur et la base de données - rendant tout ce processus aussi simple et gérable que possible.
Nous pouvons dire que la pile est un certain ensemble de technologies utilisées pour résoudre ce problème.
Bien qu'il existe de nombreuses piles qui méritent d'être discutées, certaines d'entre elles sont plus populaires que d'autres aujourd'hui. L'une de ces piles populaires s'appelle MEAN et comprend:
- M ongoDb
- E xpress.js
- A ngular.js
- N ode.js
Aujourd'hui, nous allons parler de la pile MERN, qui est très similaire à MEAN sauf que Angular.js est remplacé ici par React.js. Ainsi, nous pouvons utiliser MongoDB comme base de données, Node.js et Express, respectivement, pour le serveur et le routage, et React.js - pour créer la partie client avec laquelle l'utilisateur va interagir.
Comment se déroule le développement avec cette pile?
Avant de passer à toutes les subtilités, jetons un regard général sur la façon dont tous ces éléments fonctionnent ensemble. Personnellement, il m'a fallu un certain temps pour y entrer, car mon expérience est liée à PHP, où les parties client et serveur sont quelque peu mélangées.
1. La partie serveur (Node et Express.js) et la partie client (React.js)Tout d'abord, vous devez comprendre que la partie serveur et la partie client sont des entités distinctes. La partie client peut être dans le même référentiel avec le serveur, ou peut-être dans un tout autre.
2. Les terminaux API sont utilisés pour la communicationSi vous réfléchissez déjà à la façon de vous faire des amis des parties client et serveur, je répondrai: cela se fait via l'API. Une API (interface de programme d'application) est créée sur le serveur, où nous obtiendrons des «terminaux» à travers lesquels l'application située dans la partie client peut interagir avec le serveur.
Expliquons sur les doigts: imaginez que votre main gauche est du côté serveur et votre main droite du côté client.
Maintenant, pliez vos mains et tournez vos doigts ensemble comme si vous serriez la main. C'est ainsi que fonctionnent les langages de modèles. Ils vous permettent d'afficher simplement un balisage avec les données sauvegardées avec les serveurs - et en eux les composants client et serveur se chevauchent dans une large mesure.
Maintenant, ouvrez vos mains. Écartez vos doigts aussi largement que possible et faites en sorte que les mains gauche et droite ne touchent que du bout des doigts. C'est ainsi que fonctionne la pile MERN. La partie serveur fournit des terminaux (bout des doigts de la main gauche) pour accéder au serveur, auquel le client envoie des appels (du bout des doigts de la main droite) et à travers ces points de contact échange des informations avec le serveur (main gauche).
J'espère qu'elle est devenue un peu plus claire, et sinon, oubliez toute cette métaphore, comme si je ne l'avais pas mentionnée.
Notre côté serveur de Node.js et Express.js
Bien que je ne vais pas donner ici des instructions pas à pas sur la façon de construire cette pile (c'est un sujet pour un article séparé), je voudrais considérer les différents éléments de la pile qui sont généralement utilisés ou peuvent y être utilisés. J'ai lu moi-même plusieurs manuels qui expliquaient comment configurer le serveur, mais je n'ai pas expliqué pourquoi ces bibliothèques particulières sont utilisées à cet effet.
Après avoir créé le fichier app.js, vous devrez installer un certain nombre de packages. Voici les packages les plus courants que j'ai déjà utilisés dans mes projets avec Express.js - peut-être qu'ils vous seront utiles également.
- Express.js est un cadre pour créer des applications Web. Il a une fonctionnalité intégrée pour résoudre de nombreux problèmes, en particulier, pour établir le routage.
- Mongoose est un gestionnaire de données d'objets (ODM) qui assure l'interopérabilité entre une application express.js et une base de données MongoDB.
- BodyParser est une bibliothèque qui permet à l'application express.js de lire le corps (c'est-à-dire le contenu) des demandes entrantes.
- DotENV - vous permet d'utiliser des fichiers avec l'extension .env pour travailler avec des données confidentielles.
- Passport.js - fournit une authentification dans notre application et fournit plusieurs méthodes d'authentification différentes.
- Validateur - validation simple de nombreux types de données
- bCrypt - cryptage des données sensibles, telles que les mots de passe
- Nodemon - «redémarrage à chaud» pour notre serveur de nœuds en cas de changement de situation; Grâce à Nodemon, vous ne pouvez pas arrêter ou redémarrer le serveur après avoir effectué des modifications.
Bien sûr, il existe de nombreux autres packages, mais d'après mon expérience, ce sont ces bibliothèques qui sont utilisées le plus souvent.
Donc, après avoir trié certains des packages les plus utilisés, regardons le code. Pour commencer - notre serveur:

Il s'agit d'un simple serveur API. Comme vous pouvez le voir, il est équipé de la fonctionnalité de base CRUD (Create-Read-Update-Delete) - rien de surnaturel. En y regardant de plus près, nous voyons que
res.json()
est utilisé ici pour fournir des données de sortie pour une URL spécifique - c'est-à-dire que HTML ou un autre modèle n'est pas utilisé pour la sortie. C'est ainsi que nous construisons nos API en ouvrant l'accès aux données à React.js.
Vous pourriez également remarquer que je viens de pointer mangouste vers mon propre serveur mongodb installé sur mon ordinateur. Pour qu'un tel mécanisme fonctionne correctement, MongoDB doit être installé sur votre ordinateur et fonctionner. Si cela ne fonctionne pas, ouvrez simplement la fenêtre de la console et entrez la commande suivante:

Il démarrera le serveur MongoDB sur votre machine locale. Étant donné que tout cela se fait localement, vous ne pourrez pas voir mes publications si vous exécutez le code à partir du référentiel. Nous devons écrire nous-mêmes du nouveau contenu. Si vous avez besoin d'un talon de contenu, je recommande l'excellent générateur
Fillerama.io ,
découpant le texte de certains de mes films et émissions de télévision préférés.
Si vous souhaitez tester le serveur vous-même, vous pouvez le démarrer avec la commande suivante:

Une fois que le serveur a démarré et nous a indiqué qu'il fonctionne sur le port 3333, ainsi que qu'il s'est connecté à MongoDB, vous pouvez ouvrir
Postman et tester nos itinéraires là-bas. En ce qui concerne les options GET, vous pouvez simplement insérer l'itinéraire et cliquer sur «Envoyer». Dans le cas de POST, vous devrez sélectionner «Corps» et remplir les champs pour l'en-tête et le contenu principal.
Note côté client
Maintenant que nous avons configuré et lancé notre serveur, nous pouvons commencer à travailler sur le client avec lequel nos utilisateurs interagiront. Le client sera écrit dans React.js, et cela peut être fait de plusieurs manières différentes.
La première consiste simplement à ajouter toutes les bibliothèques nécessaires pour le côté client (react, react-dom, react-router, etc.) toutes dans le même fichier
package.json
où nous avons écrit les bibliothèques du serveur. C'est exactement ce que j'ai fait dans ce projet, mais je dois dire que je ne pense pas que cette option soit optimale. Je pense qu'à mesure que notre projet se développe, la base de code deviendra de plus en plus confuse, et si vous utilisez uniquement cette méthode, travailler avec elle deviendra plus compliqué à l'avenir. J'ai préféré ce chemin dans l'application décrite précisément parce que je sais avec certitude: il ne grandira pas et ne changera pas du tout. Cette application est écrite uniquement à des fins de démonstration.
La deuxième approche (et à mon avis) la plus optimale consiste à créer un référentiel séparé pour le côté serveur et un autre pour le client. Comme précédemment, nous pouvons facilement cloner le référentiel de la partie client dans le répertoire avec notre projet sans aucun problème, nous devons seulement nous assurer que la partie client est répertoriée dans notre fichier
.gitignore
. Par exemple, dans la structure de fichiers de cette application, il existe un répertoire
client
, où se trouve tout le code pièce client. Nous pourrions le prendre dans un référentiel complètement séparé, puis ajouter simplement l'entrée suivante au fichier
.gitignore
de notre référentiel avec le côté serveur:

En ajoutant le dossier
client
au fichier
.gitignore
, nous garantissons que le système ne percevra pas ce dossier comme le deuxième référentiel du projet. De plus, cette approche facilite le travail de refonte ou de remplacement de la partie client, puisque la partie serveur n'est pas du tout affectée.
La façon dont votre application full-stack sera conçue dépend entièrement de vous. Il me semble simplement que si vous gardez des référentiels séparés pour les parties client et serveur, la structure de l'application sera un peu plus précise.
Nous créons une partie client sur React.js
Maintenant, après avoir compris l'organisation du projet, parlons en fait du code client. Ci-dessous se trouve mon fichier
app.js
pour une application sur React.js, et je n'insérerai pas de code pour chaque composant dans ce post, je laisse juste un
lien vers le référentiel et explique ce que fait chacun des composants React.
Et voici à quoi ressemblera la capture d'écran de la page principale de notre application:

Comme vous pouvez le voir,
app.js
absolument rien de compliqué. Il existe un <Router> qui vous permet de configurer des itinéraires dans React.js qui affichent divers composants en fonction de leur URL. Voici les autres composants qui seront utilisés dans notre application React.js:
- En - tête - La barre de navigation située en haut de l'écran
- Index - Répertorie les entrées de blog disponibles
- Nouveau - Le formulaire à travers lequel l'utilisateur peut créer un nouveau message
- Unique - Affiche une entrée de blog spécifique en fonction de son
id
- Modifier - Le formulaire à travers lequel l'utilisateur peut mettre à jour l'entrée de blog trouvée par
id
Nous utilisons Axios pour effectuer des appels http vers les terminaux API, puis utilisons React.js pour afficher les données à notre guise. Dans cet article, je donnerai du code Index.js pour rendre plus clair comment tout cela fonctionne ensemble.

Dans le code ci-dessus, un composant de classe est impliqué, nous permettant d'utiliser des méthodes d'état et de cycle de vie. Cela est nécessaire car les appels Axios doivent être effectués dans la méthode du cycle de vie
componentDidMount()
. Il convient de noter que j'obtenais une erreur CORS lorsque j'essayais d'appeler mon API locale. Pour résoudre ce problème, j'ai ajouté plusieurs en-têtes au fichier server.js sur mon serveur Express - et cela a fonctionné. Ce code est noté dans les commentaires sur le fichier server.js.
Assurons-nous que les robots de recherche lisent normalement notre application React.js.Pour terminer, je voudrais parler brièvement du rendu. Si vous lancez notre site et accédez directement à un article de blog, il peut y avoir des problèmes d'affichage du contenu. Dans ce cas, la navigation sur le site sera gênante non seulement pour les utilisateurs, mais également pour les robots de recherche qui indexent le contenu. Pour contourner ce problème, je recommande d'utiliser des outils tels que Gatsby js ou Next js. Ces deux solutions sont différentes l'une de l'autre, mais les deux peuvent être utiles, selon ce dont vous avez besoin.
Gatsby js est un générateur de site statique. Vous pouvez écrire un site sur React.js, puis Gatsby le transformera en fichiers statiques pendant la construction, ce qui rendra le site ultra-rapide. Gatsby est livré avec de nombreux plugins utiles qui rendent l'outil presque universel. Soit dit en passant, mon site a été créé en utilisant Gatsby.js! Étant donné que les fichiers statiques sont créés lors de l'assemblage, le site doit être reconstruit chaque fois que le contenu d'origine change.
Next.js , à son tour, est un composant serveur pour afficher les sites React.js. De nombreuses fonctionnalités utiles y sont intégrées, en particulier le routage, le fractionnement de code, les composants conçus et bien plus encore. Le rendu du serveur signifie que les données seront mises à jour automatiquement, comme cela se fait sur le serveur, mais, avant d'être affichées dans la fenêtre du navigateur, l'étape de rendu aura lieu. C'est pourquoi il ne devrait pas y avoir de problème avec l'affichage des données à l'utilisateur, et les robots de recherche feront également leur travail sans problème.
Il existe de nombreuses autres solutions de ce type, mais j'ai surtout entendu parler de ces deux-là, et lorsque j'ai travaillé sur ce projet, je les ai utilisées. Les deux sont parfaitement documentés, il est donc facile de traiter rapidement les deux et de se mettre au travail.
Réflexions finales sur la pile MERN
J'espère que cet article vous a aidé un peu plus précisément à savoir comment fonctionne la pile MERN. Dans ce document, nous prenons simplement MongoDB, Express.js et Node.js et créons à partir d'eux un serveur qui fournit déjà des terminaux API via lesquels notre application React.js peut accéder aux données. Alors maintenant, vous comprenez beaucoup, il est temps de faire de grandes choses!