Nouveau : Datasets open source gratuits disponibles !Decouvrir →
Avance 25 min NestJS

Optimiser les performances NestJS

Pourquoi Optimiser les performances NestJS ?

Dans un monde où la performance est une priorité, optimiser les performances de votre application NestJS peut faire toute la différence. Que vous travailliez sur une petite API d'entreprise ou une grande application web monolithique, des milliers d'utilisateurs peuvent être impliqués et chaque milliseconde compte. Un exemple concret : une application de messagerie en temps réel doit pouvoir traiter des centaines de messages par seconde pour garantir une expérience utilisateur fluide.

Prerequis

  • Connaissances en JavaScript/TypeScript
  • Familiarité avec NestJS (Controllers, Services, Modules)
  • Compréhension de la gestion des requêtes et réponses HTTP
  • Connaissance des concepts asynchrones en JavaScript/TypeScript

Outils à installer :

  • Node.js v14.x ou plus tard
  • npm v6.x ou plus tard
  • NestJS CLI (npm install -g @nestjs/cli)
  • IDE ou éditeur de texte (VSCode recommandé)

Concepts fondamentaux

1. Asynchronisme avec async et await

La gestion des opérations asynchrones est cruciale pour les performances.

// ❌ Mauvais : Utilisation de callbacks
function getUser(userId, callback) {
    setTimeout(() => {
        const user = { id: userId, name: 'John' };
        callback(user);
    }, 1000);
}

getUser(1, (user) => {
    console.log('User:', user);
});
typescript
// ✅ Correct : Utilisation de async/await
async function getUser(userId) {
    return new Promise((resolve) => {
        setTimeout(() => {
            const user = { id: userId, name: 'John' };
            resolve(user);
        }, 1000);
    });
}

(async () => {
    try {
        const user = await getUser(1);
        console.log('User:', user);
    } catch (error) {
        console.error(error);
    }
})();

2. Utilisation de @Injectable pour les services

Les services NestJS sont des composants qui contiennent la logique métier et peuvent être injectés dans les contrôleurs.

// src/user/user.service.ts
import { Injectable } from '@nestjs/common';
import { User } from './user.entity';

@Injectable()
export class UserService {
    private users: User[] = [
        { id: 1, name: 'John' },
        { id: 2, name: 'Jane' }
    ];

    async findUserById(id: number): Promise<User> {
        return this.users.find(user => user.id === id);
    }
}

3. Utilisation de @Controller pour les contrôleurs

Les contrôleurs NestJS gèrent les requêtes HTTP et retournent les réponses.

// src/user/user.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('users')
export class UserController {
    constructor(private readonly userService: UserService) {}

    @Get(':id')
    async getUser(@Param('id') id: string): Promise<User> {
        return this.userService.findUserById(parseInt(id));
    }
}

4. Utilisation de @Module pour les modules

Les modules NestJS regroupent des contrôleurs, des services et d'autres composants.

// src/user/user.module.ts
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';

@Module({
  controllers: [UserController],
  providers: [UserService],
})
export class UserModule {}

Mise en pratique : projet fil rouge

Étape 1 : Création du projet NestJS

nest new task-manager
cd task-manager
npm install --save class-validator class-transformer @nestjs/typeorm typeorm pg

Étape 2 : Création d'une entité Task

// src/task/task.entity.ts
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity()
export class Task {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({ length: 255 })
    title: string;

    @Column({ default: false })
    completed: boolean;
}

Étape 3 : Création d'un service pour les tâches

// src/task/task.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Task } from './task.entity';

@Injectable()
export class TaskService {
    constructor(
        @InjectRepository(Task)
        private readonly taskRepository: Repository<Task>,
    ) {}

    async findAll(): Promise<Task[]> {
        return this.taskRepository.find();
    }

    async findOne(id: number): Promise<Task> {
        return this.taskRepository.findOne(id);
    }

    async create(task: Task): Promise<Task> {
        return this.taskRepository.save(task);
    }

    async update(id: number, task: Task): Promise<Task> {
        await this.taskRepository.update(id, task);
        return this.taskRepository.findOne(id);
    }

    async delete(id: number): Promise<void> {
        await this.taskRepository.delete(id);
    }
}

Étape 4 : Création d'un contrôleur pour les tâches

// src/task/task.controller.ts
import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
import { TaskService } from './task.service';
import { Task } from './task.entity';

@Controller('tasks')
export class TaskController {
    constructor(private readonly taskService: TaskService) {}

    @Get()
    async findAll(): Promise<Task[]> {
        return this.taskService.findAll();
    }

    @Get(':id')
    async findOne(@Param('id') id: number): Promise<Task> {
        return this.taskService.findOne(id);
    }

    @Post()
    async create(@Body() task: Task): Promise<Task> {
        return this.taskService.create(task);
    }

    @Put(':id')
    async update(@Param('id') id: number, @Body() task: Task): Promise<Task> {
        return this.taskService.update(id, task);
    }

    @Delete(':id')
    async delete(@Param('id') id: number): Promise<void> {
        await this.taskService.delete(id);
    }
}

Étape 5 : Configuration de la base de données

Modifier src/typeorm.config.ts :

// src/typeorm.config.ts
export default {
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'your_username',
  password: 'your_password',
  database: 'task_manager',
  entities: [__dirname + '/**/*.entity{.ts,.js}'],
  synchronize: true,
};

Étape 6 : Migrer le schéma de la base de données

npm install --save-dev typeorm-generator-cli pg
npx typeorm-generator -h localhost -d task_manager -u your_username -p your_password -o src/task/entities.ts

Erreurs fréquentes et debugging

1. Error: Cannot find module 'typeorm'

// ❌ Mauvais : Package non installé
import { Repository } from 'typeorm';
bash
npm install --save typeorm

2. TypeError: Cannot read property 'findOne' of undefined

// ❌ Mauvais : Injection de service incorrecte
constructor(private readonly taskService) {}
typescript
// ✅ Correct : Injection de service correcte
constructor(private readonly taskService: TaskService) {}

3. Error: No database connection is active

// ❌ Mauvais : Configuration de la base de données incorrecte
export default {
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'wrong_username', // Erreur ici
  password: 'your_password',
  database: 'task_manager',
  entities: [__dirname + '/**/*.entity{.ts,.js}'],
  synchronize: true,
};
typescript
// ✅ Correct : Configuration de la base de données correcte
export default {
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'your_username', // Correction ici
  password: 'your_password',
  database: 'task_manager',
  entities: [__dirname + '/**/*.entity{.ts,.js}'],
  synchronize: true,
};

Pour aller plus loin

1. Utilisation de @ValidationPipe pour la validation des données entrantes

2. Optimisation avec async/await et Promise.all

3. Utilisation de @InjectConnection pour la gestion des connexions

Défi pratique : Implémentez un système de pagination pour votre API de tâches. Cela implique d'ajouter des paramètres de requête pour la page et le nombre de résultats par page, puis de modifier les services et contrôleurs pour prendre en compte ces paramètres.


Ce tutoriel offre une compréhension approfondie des concepts clés de NestJS et montre comment les mettre en œuvre dans un projet réel. En suivant ces étapes, vous serez bien équipé pour améliorer la performance de vos applications NestJS.

Besoin d'aide sur NestJS ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Quelles sont les meilleures pratiques pour améliorer la performance d'une application NestJS ?
Pour optimiser la performance d'une application NestJS, il est recommandé de suivre plusieurs bonnes pratiques : utiliser le pattern de conception Singleton pour réutiliser les instances des services et des contrôleurs; éviter les opérations bloquantes en utilisant des promesses et des observables; et mettre en cache les résultats des appels fréquents à l'aide du middleware ou des intercepteurs.
Comment configurer NestJS pour qu'il utilise plusieurs workers afin d'augmenter la capacité de traitement ?
Pour utiliser plusieurs workers dans une application NestJS, vous pouvez configurer le module `Cluster` natif de Node.js. Cela permet à votre application de créer et gérer plusieurs instances du processus principal qui peuvent traiter les requêtes en parallèle, augmentant ainsi la capacité globale de traitement.
Quel est l'impact des middleware et des intercepteurs sur les performances d'une application NestJS ?
Les middleware et les intercepteurs jouent un rôle important dans la performance d'une application NestJS. Ils permettent de modifier ou de manipuler les requêtes et les réponses sans ajouter de temps significatif à leur traitement, en particulier lorsqu'ils sont utilisés pour l'authentification, le logging ou la mise en cache des données.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.