L'auteur a sélectionnéSoftware in the Public Interest Inc pour recevoir un don dans le cadre du programmeWrite for DOnations.
introduction
Nest.js est un framework JavaScript évolutif côté serveur construit avec TypeScript qui préserve toujours la compatibilité avec JavaScript, ce qui en fait un outil efficace pour créer des applications back-end efficaces et fiables. Son architecture modulaire fournit un modèle de conception structurel et mature au monde du développement de Node.js.
Vue.js est un framework JavaScript frontal pour la création d'interfaces utilisateur. Il possède une API simple, mais très puissante, ainsi que de grandes performances. Vue.js is capable of powering the front-end layer and logic of any web application irrespective of the size. La facilité d'intégration avec d'autres bibliothèques ou des projets existants en fait un choix parfait pour la plupart des applications Web modernes.
Dans ce didacticiel, vous construirez une application Nest.js pour vous familiariser avec ses blocs de construction ainsi que les principes fondamentaux de la création d’applications Web modernes. Vous aborderez ce projet en séparant l’application en deux sections différentes: l’interface et l’arrière-plan. Tout d’abord, vous allez vous concentrer sur l’API d’arrière-plan RESTful construite avec Nest.js. Vous vous concentrerez ensuite sur l’interface que vous construirez avec Vue.js. Les deux applications fonctionneront sur des ports différents et fonctionneront comme des domaines distincts.
Vous allez créer une application de blog avec laquelle les utilisateurs peuvent créer et enregistrer un nouveau message, afficher les messages sauvegardés sur la page d'accueil et exécuter d'autres processus tels que la modification et la suppression de messages. En outre, vous connecterez votre application et conserverez ses données avecMongoDB, qui est une base de données NoSQL sans schéma qui peut recevoir et stocker des documents JSON. Ce tutoriel se concentre sur la construction de votre application dans un environnement de développement. Pour un environnement de production, vous devez également envisager l'authentification de l'utilisateur pour votre application.
Conditions préalables
Pour compléter ce tutoriel, vous aurez besoin de:
-
Une installation locale deNode.js (au moins v6) etnpm (au moins v5.2). Node.js is a JavaScript run-time environment that allows you to run your code outside of the browser. Il est livré avec un gestionnaire de packages pré-installé appelé
npm
, qui vous permet d'installer et de mettre à jour des packages. Pour les installer sur macOS ou Ubuntu 18.04, suivez les étapes deHow to Install Node.js and Create a Local Development Environment on macOS ou de la section «Installation à l'aide d'un PPA» deHow To Install Node.js on Ubuntu 18.04. -
MongoDB installé sur votre machine. Suivez les instructionshere pour le télécharger et l'installer selon le système d'exploitation de votre choix. Pour réussir l'installation de MongoDB, vous pouvez soit l'installer en utilisantHomebrew surMac, soit en le téléchargeant depuis leMongoDB website.
-
Une compréhension de base de TypeScript et deJavaScript.
-
Un éditeur de texte installé, tel queVisual Studio Code,Atom ouSublime Text.
[.note] #Note: Ce didacticiel utilise une machine macOS pour le développement. Si vous utilisez un autre système d'exploitation, vous devrez peut-être utilisersudo
pour les commandesnpm
tout au long du didacticiel.
#
[[step-1 -—- Installing-nest-js-and-other-dependencies]] == Étape 1 - Installation de Nest.js et d'autres dépendances
Dans cette section, vous allez commencer à utiliser Nest.js en installant l’application et ses dépendances requises sur votre ordinateur local. Vous pouvez facilement installer Nest.js en utilisant lesCLI fournis par Nest.js ou en installant le projet de démarrage à partir de GitHub. Pour les besoins de ce didacticiel, vous utiliserez la CLI pour configurer l’application. Pour commencer, exécutez la commande suivante à partir du terminal pour l’installer globalement sur votre ordinateur:
npm i -g @nestjs/cli
Vous verrez une sortie semblable à celle-ci:
Output@nestjs/[email protected]
added 220 packages from 163 contributors in 49.104s
Pour confirmer votre installation de l'interface de ligne de commande Nest, exécutez cette commande à partir de votre terminal:
nest --version
La sortie affiche la version actuelle installée sur votre ordinateur:
Output5.8.0
Vous utiliserez la commandenest
pour gérer votre projet et l’utiliserez pour générer des fichiers pertinents, tels que le contrôleur, les modules et les fournisseurs.
Pour commencer le projet de ce didacticiel, utilisez la commandenest
pour créer un nouveau projet Nest.js nomméblog-backend
en exécutant la commande suivante à partir de votre terminal:
nest new blog-backend
Immédiatement après l'exécution de la commande,nest
vous demandera de fournir des informations de base telles que lesdescription
,version
etauthor
. Allez-y et fournissez les détails appropriés. Appuyez surENTER
sur votre ordinateur pour continuer après avoir répondu à chaque invite.
Ensuite, vous choisirez un gestionnaire de paquets. Pour les besoins de ce didacticiel, sélectionneznpm
et appuyez surENTER
pour commencer l'installation de Nest.js.
Cela générera un nouveau projet Nest.js dans un dossierblog-backend
de votre dossier de développement local.
Ensuite, accédez au dossier du nouveau projet à partir de votre terminal:
cd blog-backend
Exécutez la commande suivante pour installer d'autres dépendances de serveur:
npm install --save @nestjs/mongoose mongoose
Vous avez installé@nestjs/mongoose
, qui est un package dédié Nest.js pour un outil de modélisation d’objet pour MongoDB, etmongoose
, qui est un package pour Mongoose.
Vous allez maintenant lancer l’application à l’aide de la commande suivante:
npm run start
Maintenant, si vous accédez àhttp://localhost:3000
depuis votre navigateur préféré, vous verrez votre application en cours d'exécution.
Vous avez généré le projet avec succès en exploitant la disponibilité de la commande Nest CLI. Ensuite, vous avez exécuté l'application et y avez accédé sur le port par défaut3000
sur votre machine locale. Dans la section suivante, vous allez pousser l’application plus loin en configurant la configuration de la connexion à la base de données.
[[step-2 -—- configuration-and-connection-with-the-database]] == Étape 2 - Configuration et connexion avec la base de données
Dans cette étape, vous allez configurer et intégrer MongoDB à votre application Nest.js. Vous utiliserez MongoDB pour stocker des données pour votre application. MongoDB stocke ses données dansdocuments sous forme de pairesfield : value. Pour accéder à cette structure de données, vous utiliserezMongoose, qui est une modélisation de document objet (ODM) qui vous permet de définir des schémas représentant les types de données stockées par une base de données MongoDB.
Pour démarrer MongoDB, ouvrez une fenêtre de terminal séparée afin que l'application puisse continuer à s'exécuter, puis exécutez la commande suivante:
sudo mongod
Cela démarrera le service MongoDB et exécutera la base de données en arrière-plan de votre ordinateur.
Ouvrez le projetblog-backend
dans votre éditeur de texte et accédez à./src/app.module.ts
. Vous pouvez configurer une connexion à la base de données en incluant lesMongooseModule
installés dans lesApplicationModule
racine. Pour ce faire, mettez à jour le contenu enapp.module.ts
avec les lignes en surbrillance suivantes:
~/blog-backend/src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
@Module({
imports: [
MongooseModule.forRoot('mongodb://localhost/nest-blog', { useNewUrlParser: true }),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule { }
Dans ce fichier, vous utilisez la méthodeforRoot()
pour fournir la connexion à la base de données. Enregistrez et fermez le fichier une fois l’édition terminée.
Avec cela en place, vous avez configuré la connexion à la base de données en utilisant le module Mongoose pour MongoDB. Dans la section suivante, vous allez créer un schéma de base de données à l'aide de la bibliothèque Mongoose, d'une interface TypeScript et d'un schéma d'objet de transfert de données (DTO).
[[step-3 -—- creation-a-database-schema-interfaces-and-dto]] == Étape 3 - Création d'un schéma de base de données, d'interfaces et d'un DTO
Dans cette étape, vous allez créer unschema,interface et undata transfer object pour votre base de données en utilisant Mongoose. Mongoose aide à gérer les relations entre les données et fournit une validation de schéma pour les types de données. Pour vous aider à définir la structure et le type de données des données dans la base de données de votre application, vous créerez des fichiers qui détermineront les éléments suivants:
-
database schema: il s'agit d'une organisation des données sous forme de modèle pour définir la structure et les types de données que la base de données doit stocker.
-
interfaces: les interfaces TypeScript sont utilisées pour la vérification de type. Il peut être utilisé pour définir les types de données à transmettre pour une application.
-
data transfer object: il s'agit d'un objet qui définit la manière dont les données seront envoyées sur le réseau et transportent les données entre les processus.
Pour commencer, retournez sur votre terminal où l'application est en cours d'exécution et arrêtez le processus avecCTRL + C
, puis accédez au dossier./src/
:
cd ./src/
Ensuite, créez un répertoire nomméblog
, et un dossierschemas
dans celui-ci:
mkdir -p blog/schemas
Dans le dossierschemas
, créez un nouveau fichier appeléblog.schema.ts
et ouvrez-le à l'aide de votre éditeur de texte. Ajoutez ensuite le contenu suivant:
~/blog-backend/src/blog/schemas/blog.schema.ts
import * as mongoose from 'mongoose';
export const BlogSchema = new mongoose.Schema({
title: String,
description: String,
body: String,
author: String,
date_posted: String
})
Ici, vous avez utilisé Mongoose pour définir le type de données que vous allez stocker dans la base de données. Vous avez indiqué que tous les champs seront stockés et n'accepteront que des valeurs de chaîne. Enregistrez et fermez le fichier une fois l’édition terminée.
Maintenant, avec le schéma de base de données déterminé, vous pouvez passer à la création des interfaces.
Pour commencer, revenez dans le dossierblog
:
cd ~/blog-backend/src/blog/
Créez un nouveau dossier nomméinterfaces
et accédez-y:
mkdir interfaces
Dans le dossierinterfaces
, créez un nouveau fichier appelépost.interface.ts
et ouvrez-le à l'aide de votre éditeur de texte. Ajoutez le contenu suivant pour définir les types de données pour unPost
:
~/blog-backend/src/blog/interfaces/post.interface.ts
import { Document } from 'mongoose';
export interface Post extends Document {
readonly title: string;
readonly description: string;
readonly body: string;
readonly author: string;
readonly date_posted: string
}
Dans ce fichier, vous avez correctement défini les types de données pour un typePost
en tant que valeurs de chaîne. Enregistrez et quittez le fichier.
Etant donné que votre application exécutera la fonctionnalité d’enregistrement de données dans la base de données, vous créerez un objet de transfert de données qui définira le mode d’envoi des données sur le réseau.
Pour ce faire, créez un dossierdto
dans le dossier./src/blog
. Dans le dossier nouvellement créé, créez un autre fichier nommécreate-post.dto.ts
Revenez dans le dossierblog
:
cd ~/blog-backend/src/blog/
Créez ensuite un dossier nommédto
et déplacez-vous dedans:
mkdir dto
Dans le dossierdto
, créez un nouveau fichier appelécreate-post.dto.ts
et ouvrez-le à l'aide de votre éditeur de texte pour ajouter le contenu suivant:
~/blog-backend/src/blog/dto/create-post.dto.ts
export class CreatePostDTO {
readonly title: string;
readonly description: string;
readonly body: string;
readonly author: string;
readonly date_posted: string
}
Vous avez marqué chacune des propriétés individuelles de la classeCreatePostDTO
comme ayant le type de donnéesstring
et commereadonly
pour éviter une mutation inutile. Enregistrez et quittez le fichier une fois l’édition terminée.
Au cours de cette étape, vous avez créé un schéma de base de données pour la base de données, une interface et un objet de transfert de données pour les données que votre base de données stockera. Ensuite, vous allez générer un module, un contrôleur et un service pour votre blog.
[[step-4 -—- creation-the-module-controller-and-service-for-the-blog]] == Étape 4 - Création du module, du contrôleur et du service pour le blog
Dans cette étape, vous allez améliorer la structure existante de l’application en créant un module pour votre blog. Ce module organisera la structure de fichier de votre application. Ensuite, vous allez créer un contrôleur pour gérer les itinéraires et traiter les demandes HTTP du client. Pour conclure, vous allez configurer un service qui traitera toute la logique métier trop complexe pour que le contrôleur de l’application puisse la traiter.
Générer un module
À l'instar du framework Web frontal angulaire, Nest.js utilise une syntaxe modulaire. Nest.js applications have a modular design; it comes installed with a single root module, which is often sufficient for a small application. Cependant, lorsqu'une application commence à se développer, Nest.js recommande une organisation à plusieurs modules, scindant le code en fonctionnalités connexes.
Unmodule dans Nest.js est identifié par le décorateur@Module()
et prend un objet avec des propriétés telles quecontrollers
etproviders
. Chacune de ces propriétés prend un tableau decontrollers
etproviders
respectivement.
Vous allez générer un nouveau module pour cette application de blog afin de mieux organiser la structure. Pour commencer, toujours dans le dossier~/blog-backend
, exécutez la commande suivante:
nest generate module blog
Vous verrez une sortie semblable à celle-ci:
OutputCREATE /src/blog/blog.module.ts
UPDATE /src/app.module.ts
La commande a généré un nouveau module nomméblog.module.ts
pour l'application et a importé le module nouvellement créé dans le module racine de l'application. Cela permettra à Nest.js de connaître un autre module en plus du module racine.
Dans ce fichier, vous verrez le code suivant:
~/blog-backend/src/blog/blog.module.ts
import { Module } from '@nestjs/common';
@Module({})
export class BlogModule {}
Vous mettrez à jour ceBlogModule
avec les propriétés requises plus tard dans le didacticiel. Enregistrez et quittez le fichier.
Générer un service
Unservice, qui peut également être appelé un fournisseur dans Nest.js, a été conçu pour supprimer la logique des contrôleurs, qui sont destinés à traiter uniquement les requêtes HTTP et à rediriger les tâches plus complexes vers les services. Les services sont des classes JavaScript simples avec un décorateur@Injectable()
au dessus. Pour générer un nouveau service, exécutez la commande suivante à partir du terminal tant que vous vous trouvez dans le répertoire du projet:
nest generate service blog
Vous verrez une sortie semblable à celle-ci:
Output CREATE /src/blog/blog.service.spec.ts (445 bytes)
CREATE /src/blog/blog.service.ts (88 bytes)
UPDATE /src/blog/blog.module.ts (529 bytes)
La commandenest
utilisée ici a créé un fichierblog.service.spec.ts
, que vous pouvez utiliser pour les tests. Il a également créé un nouveau fichierblog.service.ts
, qui contiendra toute la logique de cette application et gérera l'ajout et la récupération de documents dans la base de données MongoDB. En outre, il a automatiquement importé le service nouvellement créé et ajouté à blog.module.ts.
Le service gère toute la logique de l'application, est responsable de l'interaction avec la base de données et renvoie les réponses appropriées au contrôleur. Pour ce faire, ouvrez le fichierblog.service.ts
dans votre éditeur de texte et remplacez le contenu par ce qui suit:
~/blog-backend/src/blog/blog.service.ts
import { Injectable } from '@nestjs/common';
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { Post } from './interfaces/post.interface';
import { CreatePostDTO } from './dto/create-post.dto';
@Injectable()
export class BlogService {
constructor(@InjectModel('Post') private readonly postModel: Model) { }
async getPosts(): Promise {
const posts = await this.postModel.find().exec();
return posts;
}
async getPost(postID): Promise {
const post = await this.postModel
.findById(postID)
.exec();
return post;
}
async addPost(createPostDTO: CreatePostDTO): Promise {
const newPost = await this.postModel(createPostDTO);
return newPost.save();
}
async editPost(postID, createPostDTO: CreatePostDTO): Promise {
const editedPost = await this.postModel
.findByIdAndUpdate(postID, createPostDTO, { new: true });
return editedPost;
}
async deletePost(postID): Promise {
const deletedPost = await this.postModel
.findByIdAndRemove(postID);
return deletedPost;
}
}
Dans ce fichier, vous avez d'abord importé le module requis depuis@nestjs/common
,mongoose
et@nestjs/mongoose
. Vous avez également importé une interface nomméePost
et un objet de transfert de donnéesCreatePostDTO
.
Dans lesconstructor
, vous avez ajouté@InjectModel(
, qui injectera le modèle'
Post'
)Post
dans cette classeBlogService
. Vous pourrez désormais utiliser ce modèle injecté pour extraire toutes les publications, extraire une publication unique et effectuer d'autres activités liées à la base de données.
Ensuite, vous avez créé les méthodes suivantes:
-
getPosts()
: pour récupérer toutes les publications de la base de données. -
getPost()
: pour récupérer un seul article de la base de données. -
addPost()
: pour ajouter un nouveau message. -
editPost()
: pour mettre à jour un seul post. -
deletePost()
: pour supprimer un article particulier.
Enregistrez et quittez le fichier lorsque vous avez terminé.
Vous avez terminé la configuration et la création de plusieurs méthodes qui gèrent l’interaction correcte avec la base de données MongoDB à partir de l’API d’arrière-plan. Vous allez maintenant créer les itinéraires requis pour gérer les appels HTTP à partir d'un client frontal.
Générer un contrôleur
Au nid. js,controllers sont responsables du traitement de toutes les demandes entrantes du côté client d'une application et du renvoi de la réponse appropriée. Comme pour la plupart des autres infrastructures Web, il est important que l'application écoute une demande et y réponde.
Pour répondre à toutes les requêtes HTTP de votre application de blog, vous utiliserez la commandenest
pour générer un nouveau fichier contrôleur. Assurez-vous que vous êtes toujours dans le répertoire du projet,blog-backend
, et exécutez la commande suivante:
nest generate controller blog
Vous verrez une sortie similaire à:
OutputCREATE /src/blog/blog.controller.spec.ts (474 bytes)
CREATE /src/blog/blog.controller.ts (97 bytes)
UPDATE /src/blog/blog.module.ts (483 bytes)
La sortie indique que cette commande a créé deux nouveaux fichiers dans le répertoiresrc/blog
. Ce sontblog.controller.spec.ts
etblog.controller.ts
. Le premier est un fichier que vous pouvez utiliser pour écrire des tests automatisés pour le contrôleur nouvellement créé. Ce dernier est le fichier du contrôleur lui-même. Les contrôleurs de Nest.js sont des fichiers TypeScript décorés avec les métadonnées@Controller
. La commande a également importé le contrôleur nouvellement créé et ajouté au module de blog.
Ensuite, ouvrez le fichierblog.controller.ts
avec votre éditeur de texte et mettez-le à jour avec le contenu suivant:
~/blog-backend/src/blog/blog.controller.ts
import { Controller, Get, Res, HttpStatus, Param, NotFoundException, Post, Body, Query, Put, Delete } from '@nestjs/common';
import { BlogService } from './blog.service';
import { CreatePostDTO } from './dto/create-post.dto';
import { ValidateObjectId } from '../shared/pipes/validate-object-id.pipes';
@Controller('blog')
export class BlogController {
constructor(private blogService: BlogService) { }
@Get('posts')
async getPosts(@Res() res) {
const posts = await this.blogService.getPosts();
return res.status(HttpStatus.OK).json(posts);
}
@Get('post/:postID')
async getPost(@Res() res, @Param('postID', new ValidateObjectId()) postID) {
const post = await this.blogService.getPost(postID);
if (!post) throw new NotFoundException('Post does not exist!');
return res.status(HttpStatus.OK).json(post);
}
@Post('/post')
async addPost(@Res() res, @Body() createPostDTO: CreatePostDTO) {
const newPost = await this.blogService.addPost(createPostDTO);
return res.status(HttpStatus.OK).json({
message: "Post has been submitted successfully!",
post: newPost
})
}
}
Dans ce fichier, vous avez d'abord importé les modules nécessaires pour gérer les requêtes HTTP du module@nestjs/common
. Ensuite, vous avez importé trois nouveaux modules qui sont:BlogService
,CreatePostDTO
etValidateObjectId
. Après cela, vous avez injecté lesBlogService
dans le contrôleur via un constructeur afin d'obtenir l'accès et d'utiliser les fonctions déjà définies dans le fichierBlogService
. Il s'agit d'un modèle considéré commedependency injection utilisé dans Nest.js pour augmenter l'efficacité et améliorer la modularité de l'application.
Enfin, vous avez créé les méthodes asynchrones suivantes:
-
getPosts()
: Cette méthode exécutera la fonctionnalité de réception d'une requête HTTP GET du client pour récupérer toutes les publications de la base de données, puis retournera la réponse appropriée. Il est décoré d'un@Get(
.'
posts'
) -
getPost()
: Cela prend unpostID
comme paramètre et récupère un seul article de la base de données. En plus du paramètrepostID
passé à cette méthode, vous avez réalisé l'ajout d'une méthode supplémentaire nomméeValidateObjectId()
. Cette méthode implémente l'interfacePipeTransform
de Nest.js. Son but est de valider et de s'assurer que le paramètrepostID
peut être trouvé dans la base de données. Vous allez définir cette méthode dans la section suivante. -
addPost()
: Cette méthode gérera une requête HTTP POST pour ajouter une nouvelle publication à la base de données.
Pour pouvoir modifier et supprimer un article en particulier, vous devrez ajouter deux méthodes supplémentaires au fichierblog.controller.ts
. Pour ce faire, incluez les méthodeseditPost()
etdeletePost()
suivantes directement après la méthodeaddPost()
que vous avez précédemment ajoutée àblog.controller.ts
:
~/blog-backend/src/blog/blog.controller.ts
...
@Controller('blog')
export class BlogController {
...
@Put('/edit')
async editPost(
@Res() res,
@Query('postID', new ValidateObjectId()) postID,
@Body() createPostDTO: CreatePostDTO
) {
const editedPost = await this.blogService.editPost(postID, createPostDTO);
if (!editedPost) throw new NotFoundException('Post does not exist!');
return res.status(HttpStatus.OK).json({
message: 'Post has been successfully updated',
post: editedPost
})
}
@Delete('/delete')
async deletePost(@Res() res, @Query('postID', new ValidateObjectId()) postID) {
const deletedPost = await this.blogService.deletePost(postID);
if (!deletedPost) throw new NotFoundException('Post does not exist!');
return res.status(HttpStatus.OK).json({
message: 'Post has been deleted!',
post: deletedPost
})
}
}
Ici vous avez ajouté:
-
editPost()
: Cette méthode accepte un paramètre de requête depostID
et effectuera la fonctionnalité de mise à jour d'un seul post. Il a également utilisé la méthodeValidateObjectId
pour fournir une validation appropriée pour le message que vous devez modifier. -
deletePost()
: Cette méthode acceptera un paramètre de requête depostID
et supprimera une publication particulière de la base de données.
Comme pour lesBlogController
, chacune des méthodes asynchrones que vous avez définies ici a un décorateur de métadonnées et prend un préfixe que Nest.js utilise comme mécanisme de routage. Il contrôle quel contrôleur reçoit quelles requêtes et pointe vers les méthodes qui doivent traiter la requête et renvoyer une réponse, respectivement.
Par exemple, leBlogController
que vous avez créé dans cette section a un préfixe deblog
et une méthode nomméegetPosts()
qui prend un préfixe deposts
. Cela signifie que toute requête GET envoyée à un point final deblog/posts
(http:localhost:3000/blog/posts
) sera traitée par la méthode `getPosts ()`. Cet exemple est similaire à celui utilisé par d'autres méthodes pour gérer les demandes HTTP.
Enregistrez et quittez le fichier.
Pour obtenir le fichierblog.controller.ts
complet, visitez lesDO Community repository de cette application.
Dans cette section, vous avez créé un module pour que l'application soit mieux organisée. Vous avez également créé un service pour gérer la logique applicative de l'application en interagissant avec la base de données et en renvoyant la réponse appropriée. Enfin, vous avez généré un contrôleur et créé les méthodes requises pour gérer les requêtes HTTP telles queGET
,POST
,PUT
etDELETE
côté client. Dans l’étape suivante, vous allez terminer la configuration de votre back-end.
[[step-5 -—- creation-an-extra-validation-for-mongoose]] == Étape 5 - Création d'une validation supplémentaire pour Mongoose
Vous pouvez identifier chaque article de votre application de blog par un identifiant unique, également appeléPostID
. Cela signifie que pour aller chercher un article, vous devrez passer cet ID en tant que paramètre de requête. Pour valider ce paramètrepostID
et vous assurer que la publication est disponible dans la base de données, vous devez créer une fonction réutilisable qui peut être initialisée à partir de n'importe quelle méthode dans lesBlogController
.
Pour configurer cela, accédez au dossier./src/blog
:
cd ./src/blog/
Ensuite, créez un nouveau dossier nomméshared
:
mkdir -p shared/pipes
Dans le dossierpipes
, à l'aide de votre éditeur de texte, créez un nouveau fichier appelévalidate-object-id.pipes.ts
et ouvrez-le. Ajoutez le contenu suivant pour définir les donnéespostID
acceptées:
~/blog-backend/src/blog/shared/pipes/validate-object-id.pipes.ts
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import * as mongoose from 'mongoose';
@Injectable()
export class ValidateObjectId implements PipeTransform {
async transform(value: string, metadata: ArgumentMetadata) {
const isValid = mongoose.Types.ObjectId.isValid(value);
if (!isValid) throw new BadRequestException('Invalid ID!');
return value;
}
}
La classeValidateObjectId()
implémente la méthodePipeTransform
du module@nestjs/common
. Il a une seule méthode nomméetransform()
qui prend en valeur comme paramètre -postID
dans ce cas. Avec la méthode ci-dessus, toute requête HTTP du frontend de cette application avec unpostID
qui ne peut pas être trouvé dans la base de données sera considérée comme invalide. Enregistrez et fermez le fichier.
Après avoir créé à la fois le service et le contrôleur, vous devez configurer le modèlePost
basé sur lesBlogSchema
. Cette configuration peut être configurée dans la racineApplicationModule
, mais dans ce cas, la construction du modèle dansBlogModule
maintiendra l'organisation de votre application. Ouvrez le./src/blog/blog.module.ts
et mettez-le à jour avec les lignes en surbrillance suivantes:
~/blog-backend/src/blog/blog.module.ts
import { Module } from '@nestjs/common';
import { BlogController } from './blog.controller';
import { BlogService } from './blog.service';
import { MongooseModule } from '@nestjs/mongoose';
import { BlogSchema } from './schemas/blog.schema';
@Module({
imports: [
MongooseModule.forFeature([{ name: 'Post', schema: BlogSchema }])
],
controllers: [BlogController],
providers: [BlogService]
})
export class BlogModule { }
Ce module utilise la méthodeMongooseModule.forFeature()
pour définir les modèles à enregistrer dans le module. Sans cela, injecter lesPostModel
dans lesBlogService
à l'aide du décorateur@injectModel()
ne fonctionnerait pas. Enregistrez et fermez le fichier lorsque vous avez fini d'ajouter le contenu.
Au cours de cette étape, vous avez créé l’API d’arrière-plan complète RESTful avec Nest.js et l’avez intégrée à MongoDB. Dans la section suivante, vous allez configurer le serveur pour autoriser les requêtes HTTP provenant d’un autre serveur, car votre application frontale s’exécutera sur un autre port.
[[step-6 -—- enabled-cors]] == Étape 6 - Activation de CORS
Une demande HTTP d'un domaine à un autre est souvent bloquée par défaut, sauf si le serveur le permet. Pour que votre application frontale fasse une demande au serveur principal, vous devez activerCross-origin resource sharing (CORS), qui est une technique qui autorise les demandes de ressources restreintes sur une page Web.
Dans Nest.js pour activer CORS, vous devez ajouter une seule méthode à votre fichiermain.ts
. Ouvrez ce fichier dans votre éditeur de texte, situé à./src/main.ts
, et mettez-le à jour avec le contenu en surbrillance suivant:
~/blog-backend/src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
await app.listen(3000);
}
bootstrap();
Enregistrez et quittez le fichier.
Maintenant que vous avez terminé la configuration du back-end, vous allez vous focaliser sur le front-end et utilisez Vue.js pour utiliser les API construites jusqu'à présent.
[[step-7 -—- creation-the-vue-js-frontend]] == Étape 7 - Création du frontend Vue.js
Dans cette section, vous allez créer votre application frontale avec Vue.js. Vue CLI est un outil standard qui vous permet de générer et d'installer rapidement un nouveau projet Vue.js sans trop de tracas.
Pour commencer, vous devez d'abord installer Vue CLI globalement sur votre ordinateur. Ouvrez un autre terminal et au lieu de travailler à partir du dossierblog-backend
, accédez au dossier de développement de votre projet local et exécutez:
npm install -g @vue/cli
Une fois le processus d'installation terminé, vous utiliserez la commandevue
pour créer un nouveau projet Vue.js:
vue create blog-frontend
Une courte invite apparaît après que vous avez entré cette commande. Choisissez l'optionmanually select features
, puis sélectionnez les fonctionnalités dont vous aurez besoin pour ce projet en appuyant surSPACE
sur votre ordinateur pour mettre en évidence plusieurs fonctionnalités. Vous sélectionnerezBabel
,Router
etLinter / Formatter
.
Pour les instructions suivantes, tapezy
pour utiliser le mode historique pour un routeur; cela garantira que le mode historique est activé dans le fichier du routeur, qui sera automatiquement généré pour ce projet. De plus, sélectionnezESLint with error prevention only
pour choisir une configuration linter / formatter. Ensuite, sélectionnezLint on save
pour des fonctionnalités supplémentaires Lint. Ensuite, sélectionnez pour enregistrer votre configuration dans undedicated config file
pour de futurs projets. Tapez un nom pour votre préréglage, commevueconfig
.
Vue.js will then start creating the application and all its required dependencies in a directory named blog-frontend
.
Une fois le processus d'installation terminé, naviguez dans l'application Vue.js:
cd blog-frontend
Ensuite, démarrez le serveur de développement avec:
npm run serve
Votre application fonctionnera surhttp://localhost:8080
.
Étant donné que vous exécuterez des requêtes HTTP dans cette application, vous devrez installer Axios, un client HTTP basé sur des promesses pour le navigateur. Ici, vous utiliserez Axios pour exécuter des requêtes HTTP à partir des différents composants de l’application. Arrêtez l'application frontale en appuyant surCTRL + C
depuis le terminal de votre ordinateur, puis exécutez la commande suivante:
npm install axios --save
Votre application frontale effectuera un appel d'API à l'API back-end sur un domaine particulier à partir de différents composants de l'application. Afin de garantir une structure appropriée pour cette application, vous pouvez créer un fichierhelper
et définir le serveurbaseURL
.
Pour commencer, depuis votre terminal toujours à l'intérieur deblog-frontend
, naviguez jusqu'au dossier./src/
:
cd ./src/
Créez un autre dossier nomméutils
:
mkdir utils
Dans le dossierutils
, à l'aide de votre éditeur de texte, créez un nouveau fichier appeléhelper.js
et ouvrez-le. Ajoutez le contenu suivant pour définir lesbaseURL
pour le projet principal Nest.js:
~blog-frontend/src/utils/helper.js
export const server = {
baseURL: 'http://localhost:3000'
}
En définissant unbaseURL
, vous pourrez l'appeler de n'importe où dans vos fichiers de composants Vue.js. Si vous devez modifier l'URL, il sera plus facile de mettre à jour lesbaseURL
dans ce fichier plutôt que dans votre application.
Dans cette section, vous avez installé Vue CLI, un outil permettant de créer une nouvelle application Vue.js. Vous avez utilisé cet outil pour créer l'applicationblog-frontend
. De plus, vous avez exécuté l'application et installé une bibliothèque appelée Axios, que vous utiliserez chaque fois qu'il y a un appel HTTP dans l'application. Ensuite, vous allez créer des composants pour l'application.
[[step-8 -—- creating-reusable-components]] == Étape 8 - Création de composants réutilisables
Vous allez maintenant créer des composants réutilisables pour votre application, qui constituent la structure standard des applications Vue.js. Le système de composants de Vue.js permet aux développeurs de créer une seule unité indépendante d'une interface pouvant avoir son propre état, son propre marquage et son propre style. Cela rend approprié que les composants de Vue.js soient réutilisables.
Chaque composant Vue.js contient trois sections différentes:
-
<template>
: contient le contenu HTML -
<script>
: contient toute la logique frontale de base et définit les fonctions -
<style>
: la feuille de style pour chaque composant séparé
Tout d’abord, vous allez commencer par créer un composant pour créer une nouvelle publication. Pour ce faire, créez un nouveau dossier nommépost
dans le dossier./src/components
, qui hébergera les composants réutilisables nécessaires pour les publications. Puis en utilisant votre éditeur de texte, dans le dossierpost
nouvellement créé, créez un autre fichier et nommez-leCreate.vue
. Ouvrez le nouveau fichier et ajoutez le code suivant, qui contient les champs de saisie nécessaires pour soumettre un message:
~blog-frontend/src/components/post/Create.vue
Create Post
Il s'agit de la section<template>
du composantCreatePost
. Il contient les éléments d’entrée HTML nécessaires à la création d’une nouvelle publication. Chacun des champs d'entrée a une directivev-model
comme attribut d'entrée. Cela permet d’assurer des liaisons de données bidirectionnelles sur chaque entrée de formulaire afin de permettre à Vue.js d’obtenir la saisie de l’utilisateur.
Ensuite, ajoutez la section<script>
au même fichier directement après le contenu précédent:
~blog-frontend/src/components/post/Create.vue
...
Ici, vous avez ajouté une méthode nomméecreatePost()
pour créer une nouvelle publication et la soumettre au serveur à l'aide d'Axios. Une fois qu'un utilisateur crée un nouveau message, l'application sera redirigée vers la page d'accueil où les utilisateurs peuvent afficher la liste des messages créés.
Vous allez configurer vue-router pour implémenter la redirection ultérieurement dans ce tutoriel.
Enregistrez et fermez le fichier une fois l’édition terminée. Pour obtenir le fichierCreate.vue
complet, visitez lesDO Community repository de cette application.
Maintenant, vous devez créer un autre composant pour éditer un article particulier. Accédez au dossier./src/components/post
et créez un autre fichier et nommez-leEdit.vue
. Ajoutez-y le code suivant qui contient la section<template>
:
~blog-frontend/src/components/post/Edit.vue
Edit Post
Cette section de modèle contient un contenu similaire à celui du composantCreatePost()
; la seule différence est qu'il contient les détails de l'article particulier qui doit être modifié.
Ensuite, ajoutez la section`
Ici, vous avez obtenu le paramètre d'itinéraireid
pour identifier une publication particulière. Vous avez ensuite créé une méthode nomméegetPost()
pour récupérer les détails de cette publication à partir de la base de données et mis à jour la page avec elle. Enfin, vous avez créé une méthodeeditPost()
pour renvoyer la publication modifiée au serveur principal avec une requête HTTP PUT.
Enregistrez et quittez le fichier. Pour obtenir le fichierEdit.vue
complet, visitez lesDO Community repository de cette application.
Maintenant, vous allez créer un nouveau composant dans le dossier./src/components/post
et le nommerPost.vue
. Cela vous permettra d'afficher les détails d'une publication particulière à partir de la page d'accueil. Ajoutez le contenu suivant àPost.vue
:
~blog-frontend/src/components/post/Post.vue
{{ post.title }}
Post by {{post.author}}, {{post.date_posted}}.
{{ post.body }}
Ce code rend les détails d'une publication qui comprend,title
,author
et la publicationbody
.
Maintenant, juste après</template>
, ajoutez le code suivant au fichier:
~blog-frontend/src/components/post/Post.vue
...
Semblable à la section<script>
du composant d'édition de publication, vous avez obtenu le paramètre d'itinéraireid
et l'avez utilisé pour récupérer les détails d'une publication particulière.
Enregistrez et fermez le fichier lorsque vous avez terminé d'ajouter le contenu. Pour obtenir le fichierPost.vue
complet, visitez lesDO Community repository de cette application.
Ensuite, pour afficher toutes les publications créées pour les utilisateurs, vous allez créer un nouveau composant. Si vous accédez au dossierviews
danssrc/views
, vous verrez un composantHome.vue
- si ce fichier n'est pas présent, utilisez votre éditeur de texte pour le créer, ajoutez le code suivant:
~blog-frontend/src/views/Home.vue
Nest Blog Tutorial
This is the description of the blog built with Nest.js, Vue.js and MongoDB
No post found at the moment
{{ post.title }}
{{ post.body }}
View Post
Edit Post
Ici, dans la section<template>
, vous avez utilisé les<router-link>
pour créer un lien pour l'édition ainsi que pour afficher un message en passant lespost._id
comme paramètre de requête. Vous avez également utilisé la directivev-if
pour rendre conditionnellement le message aux utilisateurs. S'il n'y a pas de publication de la base de données, un utilisateur ne verra que ce texte:No post found at the moment.
Enregistrez et quittez le fichier. Pour obtenir le fichierHome.vue
complet, visitez lesDO Community repository de cette application.
Maintenant, juste après la section</template>
dansHome.vue
, ajoutez la section</script>
suivante:
~blog-frontend/src/views/Home.vue
...
Dans la section<script>
de ce fichier, vous avez créé une méthode nomméefetchPosts()
pour récupérer toutes les publications de la base de données et vous avez mis à jour la page avec les données renvoyées par le serveur.
Vous allez maintenant mettre à jour le composantApp
de l’application frontale afin de créer des liens vers les composantsHome
etCreate
. Ouvrezsrc/App.vue
et mettez-le à jour avec les éléments suivants:
~blog-frontend/src/App.vue
En plus d'inclure les liens vers les composantsHome
etCreate
, vous avez également inclus la section<Style>
, qui est la feuille de style de ce composant et contient la définition des styles pour certains des éléments sur la page. Enregistrez et quittez le fichier.
Vous avez créé tous les composants requis pour votre application à cette étape. Ensuite, vous allez configurer le fichier du routeur.
[[step-9 -—- setting-up-routing]] == Étape 9 - Configuration du routage
Après avoir créé tous les composants réutilisables nécessaires, vous pouvez maintenant configurer correctement le fichier du routeur en mettant à jour son contenu avec des liens vers tous les composants que vous avez créés. Cela garantira que tous les points de terminaison de l'application frontale sont mappés sur un composant particulier pour une action appropriée. Accédez à./src/router.js
et remplacez son contenu par ce qui suit:
~blog-frontend/src/router.js
import Vue from 'vue'
import Router from 'vue-router'
import HomeComponent from '@/views/Home';
import EditComponent from '@/components/post/Edit';
import CreateComponent from '@/components/post/Create';
import PostComponent from '@/components/post/Post';
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{ path: '/', redirect: { name: 'home' } },
{ path: '/home', name: 'home', component: HomeComponent },
{ path: '/create', name: 'Create', component: CreateComponent },
{ path: '/edit/:id', name: 'Edit', component: EditComponent },
{ path: '/post/:id', name: 'Post', component: PostComponent }
]
});
Vous avez importéRouter
du modulevue-router
et l'instancié en passant les paramètresmode
etroutes
. Le mode par défaut pourvue-router
est un mode de hachage, qui utilise le hachage d'URL pour simuler une URL complète afin que la page ne soit pas rechargée lorsque l'URL change. Afin de rendre le hachage inutile, vous avez utilisé le mode historique pour effectuer une navigation URL sans rechargement de page. Enfin, dans l'optionroutes
, vous avez spécifié le chemin du noeud final - un nom pour la route et le composant qui doit être rendu lorsque la route est appelée dans l'application. Enregistrez et quittez le fichier.
Maintenant que vous avez configuré le routage vers l'application, vous devez inclure le fichier Bootstrap pour vous aider à créer un style prédéfini pour l'interface utilisateur de l'application. Pour ce faire, ouvrez le fichier./public/index.html
dans votre éditeur de texte et incluez le fichier CDN pour Bootstrap en ajoutant le contenu suivant au fichier:
~blog-frontend/public/index.html
...
blog-frontend
...
Enregistrez et quittez le fichier, puis redémarrez l'application avecnpm run serve
pour vosblog-frontend
, si elle n'est pas en cours d'exécution.
[.note] #Note: Assurez-vous que le serveur principal et l'instance MongoDB sont également en cours d'exécution. Sinon, accédez auxblog-backend
depuis un autre terminal et exécuteznpm run start
. Démarrez également le service MongoDB en exécutantsudo mongod
à partir d'un nouveau terminal.
#
Accédez à votre application à l'adresse:http://localhost:8080
. Vous pouvez maintenant tester votre blog en créant et en modifiant des messages.
Cliquez surCreate sur votre application pour voir l'écranCreate Post, qui se rapporte au fichierCreateComponent
et le rend. Entrez les valeurs dans les champs de saisie et cliquez sur le boutonCreate Post pour soumettre un message. Une fois que vous avez terminé, l'application vous redirigera vers la page d'accueil.
La page d'accueil de l'application rend lesHomeComponent
. Ce composant a une méthode qui envoie un appel HTTP pour extraire toutes les publications de la base de données et les affiche aux utilisateurs.
En cliquant sur le boutonEdit Post pour un article particulier, vous serez redirigé vers une page d'édition où vous pourrez incorporer les modifications et enregistrer votre article.
Dans cette section, vous avez configuré et configuré le routage pour l'application. Avec cela en place, votre application de blog est prête.