NestJS для JavaScript (Node.js): полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое NestJS и зачем он нужен?

NestJS — это прогрессивный фреймворк для создания эффективных, надёжных и масштабируемых серверных приложений на Node.js. Он использует выразительную архитектуру, вдохновлённую Angular, и по умолчанию построен на TypeScript, но полностью поддерживает и чистый JavaScript. NestJS абстрагирует низкоуровневые детали таких популярных библиотек, как Express (по умолчанию) или Fastify, предоставляя разработчику мощный набор инструментов для организации кода: модули, контроллеры, сервисы, провайдеры, middleware, guards, interceptors, pipes и filters.

Зачем нужен NestJS? В современной веб-разработке на Node.js часто возникает проблема организации кода: простые скрипты на Express быстро превращаются в «спагетти» при росте функциональности. NestJS решает эту проблему, навязывая чёткую модульную структуру и принципы внедрения зависимостей (Dependency Injection). Это облегчает тестирование, поддержку и масштабирование приложения. Фреймворк идеально подходит для создания REST API, GraphQL-серверов, микросервисов, а также для приложений реального времени (WebSockets).

Ключевое преимущество NestJS — его экосистема. Он предоставляет официальные модули для работы с базами данных (TypeORM, Mongoose, Prisma), аутентификацией (Passport), валидацией (class-validator), конфигурацией, очередями (Bull), кэшированием и многим другим. Благодаря этому разработчик может сосредоточиться на бизнес-логике, а не на интеграции разнородных библиотек.

Установка

Для установки NestJS используется пакетный менеджер npm (или yarn). Рекомендуется установить глобально CLI-инструмент для быстрого создания проекта:

npm install -g @nestjs/cli

После установки CLI вы можете создать новый проект командой:

nest new my-nest-project

В процессе установки вас попросят выбрать пакетный менеджер (npm, yarn или pnpm) и язык (TypeScript — рекомендуется, или JavaScript). Если вы хотите добавить NestJS в уже существующий проект, установите основные пакеты:

npm install @nestjs/core @nestjs/common @nestjs/platform-express reflect-metadata rxjs

Обратите внимание: библиотека reflect-metadata обязательна для работы декораторов.

Быстрый старт: минимальный рабочий пример

Создадим простейший REST API с одним эндпоинтом, возвращающим "Hello World".

Шаг 1: Создайте файл app.controller.js

// app.controller.js
const { Controller, Get } = require('@nestjs/common');

@Controller()
export class AppController {
    @Get()
    getHello() {
        return 'Hello World!';
    }
}

Шаг 2: Создайте файл app.module.js

// app.module.js
const { Module } = require('@nestjs/common');
const { AppController } = require('./app.controller');

@Module({
    controllers: [AppController],
})
export class AppModule {}

Шаг 3: Создайте главный файл main.js

// main.js
const { NestFactory } = require('@nestjs/core');
const { AppModule } = require('./app.module');

async function bootstrap() {
    const app = await NestFactory.create(AppModule);
    await app.listen(3000);
    console.log('Сервер запущен на http://localhost:3000');
}
bootstrap();

Шаг 4: Запустите приложение

node main.js

Теперь перейдите по адресу http://localhost:3000 — вы увидите "Hello World!".

Основные методы, классы и декораторы

Ниже приведены 8 ключевых элементов NestJS с сигнатурами, описанием и примерами на JavaScript.

1. @Module()

Сигнатура: @Module({ imports?: [], controllers?: [], providers?: [], exports?: [] })

Что делает: Декоратор, который определяет модуль — основной строительный блок приложения. Он группирует связанные контроллеры, сервисы и другие модули.

const { Module } = require('@nestjs/common');
const { UsersController } = require('./users.controller');
const { UsersService } = require('./users.service');

@Module({
    controllers: [UsersController],
    providers: [UsersService],
    exports: [UsersService], // делает сервис доступным для других модулей
})
export class UsersModule {}

2. @Controller()

Сигнатура: @Controller(prefix?: string)

Что делает: Декоратор, который определяет класс как контроллер. Он обрабатывает входящие HTTP-запросы и возвращает ответы. Необязательный префикс добавляется ко всем маршрутам внутри контроллера.

const { Controller, Get } = require('@nestjs/common');

@Controller('users') // Все маршруты будут начинаться с /users
export class UsersController {
    @Get()
    findAll() {
        return ['user1', 'user2'];
    }
}

3. @Injectable()

Сигнатура: @Injectable()

Что делает: Декоратор, который помечает класс как провайдер (сервис, репозиторий, хелпер). Это позволяет системе внедрения зависимостей NestJS автоматически создавать и управлять экземплярами этого класса.

const { Injectable } = require('@nestjs/common');

@Injectable()
export class UsersService {
    private users = ['Alice', 'Bob'];

    findAll() {
        return this.users;
    }
}

4. @Get(), @Post(), @Put(), @Delete()

Сигнатура: @Get(path?: string), @Post(path?: string) и т.д.

Что делает: Декораторы методов, которые привязывают метод класса к определённому HTTP-методу и пути. Они определяют маршрутизацию в контроллере.

const { Controller, Get, Post, Body, Param } = require('@nestjs/common');

@Controller('products')
export class ProductsController {
    @Get()
    getAll() { return ['prod1', 'prod2']; }

    @Get(':id')
    getOne(@Param('id') id) { return `Product ${id}`; }

    @Post()
    create(@Body() body) { return `Created: ${JSON.stringify(body)}`; }
}

5. @Param(), @Body(), @Query()

Сигнатура: @Param(property?: string), @Body(), @Query(property?: string)

Что делает: Декораторы параметров метода, которые извлекают данные из запроса: параметры пути (@Param), тело запроса (@Body) и query-параметры (@Query).

const { Controller, Get, Post, Param, Body, Query } = require('@nestjs/common');

@Controller('search')
export class SearchController {
    @Get(':type')
    search(
        @Param('type') type,
        @Query('q') query,
        @Body() filters
    ) {
        return { type, query, filters };
    }
}

6. NestFactory.create()

Сигнатура: NestFactory.create(moduleClass, options?)

Что делает: Статический метод, который создаёт экземпляр приложения NestJS на основе корневого модуля. Возвращает объект INestApplication, который можно настроить и запустить.

const { NestFactory } = require('@nestjs/core');
const { AppModule } = require('./app.module');

async function bootstrap() {
    const app = await NestFactory.create(AppModule);
    app.enableCors(); // Включаем CORS
    await app.listen(3000);
}
bootstrap();

7. @UsePipes() и класс ValidationPipe

Сигнатура: @UsePipes(new ValidationPipe(options?))

Что делает: Декоратор для применения пайпов (pipes) к контроллеру или методу. ValidationPipe — встроенный пайп для автоматической валидации входящих данных на основе декораторов из class-validator.

const { Controller, Post, Body, UsePipes, ValidationPipe } = require('@nestjs/common');
const { IsString, IsInt } = require('class-validator');

class CreateUserDto {
    @IsString()
    name;

    @IsInt()
    age;
}

@Controller('users')
export class UsersController {
    @Post()
    @UsePipes(new ValidationPipe({ transform: true }))
    create(@Body() createUserDto) {
        return `User created: ${createUserDto.name}`;
    }
}

8. @UseGuards() и класс AuthGuard

Сигнатура: @UseGuards(guardClass)

Что делает: Декоратор для применения гардов (guards) к контроллеру или методу. Гарды определяют, может ли запрос быть обработан (например, проверка аутентификации). AuthGuard('jwt') — встроенный гард для JWT-аутентификации.

const { Controller, Get, UseGuards } = require('@nestjs/common');
const { AuthGuard } = require('@nestjs/passport');

@Controller('profile')
export class ProfileController {
    @Get()
    @UseGuards(AuthGuard('jwt'))
    getProfile() {
        return { message: 'This is protected data' };
    }
}

Реальный практический пример: CRUD для управления задачами (Todo List)

Создадим полноценный REST API для управления задачами. Пример включает модуль, контроллер, сервис, валидацию и хранение в памяти.

Структура проекта:

  • todo.module.js — модуль
  • todo.controller.js — контроллер
  • todo.service.js — сервис
  • create-todo.dto.js — DTO для валидации
  • main.js — точка входа

1. create-todo.dto.js

const { IsString, IsBoolean, IsOptional } = require('class-validator');

class CreateTodoDto {
    @IsString()
    title;

    @IsOptional()
    @IsString()
    description;

    @IsOptional()
    @IsBoolean()
    completed;
}

module.exports = { CreateTodoDto };

2. todo.service.js

const { Injectable, NotFoundException } = require('@nestjs/common');

@Injectable()
class TodoService {
    constructor() {
        this.todos = [];
        this.idCounter = 1;
    }

    findAll() {
        return this.todos;
    }

    findOne(id) {
        const todo = this.todos.find(t => t.id === Number(id));
        if (!todo) throw new NotFoundException(`Todo with id ${id} not found`);
        return todo;
    }

    create(createTodoDto) {
        const todo = { id: this.idCounter++, ...createTodoDto, completed: false };
        this.todos.push(todo);
        return todo;
    }

    update(id, updateTodoDto) {
        const todo = this.findOne(id);
        Object.assign(todo, updateTodoDto);
        return todo;
    }

    remove(id) {
        const index = this.todos.findIndex(t => t.id === Number(id));
        if (index === -1) throw new NotFoundException(`Todo with id ${id} not found`);
        this.todos.splice(index, 1);
        return { deleted: true };
    }
}

module.exports = { TodoService };

3. todo.controller.js

const { Controller, Get, Post, Put, Delete, Param, Body, UsePipes, ValidationPipe } = require('@nestjs/common');
const { TodoService } = require('./todo.service');
const { CreateTodoDto } = require('./create-todo.dto');

@Controller('todos')
class TodoController {
    constructor() {
        this.todoService = new TodoService();
    }

    @Get()
    findAll() {
        return this.todoService.findAll();
    }

    @Get(':id')
    findOne(@Param('id') id) {
        return this.todoService.findOne(id);
    }

    @Post()
    @UsePipes(new ValidationPipe({ transform: true }))
    create(@Body() createTodoDto) {
        return this.todoService.create(createTodoDto);
    }

    @Put(':id')
    update(@Param('id') id, @Body() updateTodoDto) {
        return this.todoService.update(id, updateTodoDto);
    }

    @Delete(':id')
    remove(@Param('id') id) {
        return this.todoService.remove(id);
    }
}

module.exports = { TodoController };

4. todo.module.js

const { Module } = require('@nestjs/common');
const { TodoController } = require('./todo.controller');
const { TodoService } = require('./todo.service');

@Module({
    controllers: [TodoController],
    providers: [TodoService],
})
class TodoModule {}

module.exports = { TodoModule };

5.

Рекомендаций