Что такое 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.
Также в библиотеке
Валидация данных в Go (Golang): библиотеки, подходы и примеры кода
PDF генерация в TypeScript: библиотеки и инструменты для Node.js
Работа с изображениями на Swift: resize и crop для iOS/macOS
Машинное обучение на Go: библиотеки для Golang (ML, нейросети, NLP)
StackExchange.Redis для C# (.NET): полное руководство с примерами