← Назад к вопросам

На основе чего создан фреймворк на котором работаешь

1.8 Middle🔥 151 комментариев
#Архитектура и паттерны#Фреймворки и библиотеки

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Архитектура фреймворков, на которых я работаю

На основе моего опыта, я могу рассказать об архитектуре основных Node.js фреймворков и их базовых принципах.

1. Express.js — Middleware Stack

Express построен на простой идее: middleware chain (цепочка).

// Основной принцип Express — цепочка middleware
app.use(middleware1);      // Выполнится первым
app.use(middleware2);      // Выполнится вторым
app.get('/path', handler); // Специфичный handler

// Каждый middleware получает (req, res, next)
// и может модифицировать request или response
const middleware = (req, res, next) => {
  req.user = { id: 123 };  // Модифицируем request
  next();  // Передаем управление следующему middleware
};

// Архитектура внутри Express:
// 1. Request входит
// 2. Проходит через middleware chain
// 3. Достигает handler
// 4. Response возвращается

Базовый принцип: Linear chain processing - просто и понятно.

2. Fastify — Plugin System

Fastify построен на Plugin Architecture.

import Fastify from 'fastify';

const fastify = Fastify();

// Плагины — это функции которые расширяют fastify
fastify.register(async (fastify) => {
  fastify.get('/users', async () => {
    return { users: [] };
  });
});

// Каждый плагин — это изолированный scope
// Преимущества:
// - Изоляция
// - Переиспользование
// - Чистая архитектура

// Внутренняя архитектура:
// 1. Request приходит в HTTP handler
// 2. Выполняются pre-handler hooks
// 3. Выполняется handler с валидацией
// 4. Выполняются post-handler hooks
// 5. Response сериализуется и отправляется

Базовый принцип: Plugin-based architecture для модульности.

3. NestJS — Dependency Injection + Module System

NestJS построен на Angular-like архитектуре.

// Module — контейнер для связанного функционала
@Module({
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService]
})
export class UsersModule {}

// Controller — обрабатывает HTTP запросы
@Controller('users')
export class UsersController {
  constructor(private usersService: UsersService) {}
  
  @Get()
  async getAll() {
    return this.usersService.findAll();
  }
}

// Service — бизнес логика
@Injectable()
export class UsersService {
  constructor(private prisma: PrismaService) {}
  
  async findAll() {
    return this.prisma.user.findMany();
  }
}

// Архитектура:
// Модули <- Контроллеры <- Сервисы <- Провайдеры
// Каждый уровень имеет ясную ответственность

Базовый принцип: DI + Module System + Layered Architecture (как Spring Boot).

4. Hapi — Schema-based

Hapi построен на Schema Validation First.

const server = Hapi.server({ port: 3000 });

server.route({
  method: 'GET',
  path: '/users/{id}',
  
  // Schema для валидации request
  options: {
    validate: {
      params: Joi.object({
        id: Joi.number().required()
      }),
      query: Joi.object({
        includeProfile: Joi.boolean()
      })
    },
    
    // Встроенная аутентификация
    auth: 'jwt'
  },
  
  handler: async (request, h) => {
    return { user: {} };
  }
});

// Архитектура:
// Request -> Validate -> Auth -> Handler -> Response

Базовый принцип: Declarative validation and security-first.

5. Koa — Async/Await First

Koa построен на Async Context + Middleware.

const koa = require('koa');
const app = new koa();

// Middleware в Koa — это async функции
// Используют context (ctx) вместо (req, res)
app.use(async (ctx) => {
  ctx.body = 'Hello World';
  // ctx объект содержит request и response
});

// Архитектура похожа на Express, но с async/await первым
// Нет callback hell

Базовый принцип: Async-first middleware with context object.

Общие паттерны в Node.js фреймворках

Паттерн 1: Middleware

Req -> MW1 -> MW2 -> Handler -> Res

Используют: Express, Koa

Паттерн 2: Plugin/Module

App.register(Plugin1)
   .register(Plugin2)

Используют: Fastify, NestJS

Паттерн 3: Dependency Injection

Container -> resolve(Service) -> inject dependencies

Используют: NestJS, Hapi

Паттерн 4: Declarative Routing

@Controller()
@Get('/path')
handler() {}

Используют: NestJS, (Fastify with decorators)

На каком я основываю современные приложения

Мой идеальный фреймворк основан на:

// 1. Fastify за основу (производительность)
import Fastify from 'fastify';

// 2. DI контейнер (как в NestJS)
class Container {
  private services: Map<string, any> = new Map();
  
  register(name: string, service: any) {
    this.services.set(name, service);
  }
  
  get(name: string) {
    return this.services.get(name);
  }
}

// 3. Plugin-based modules
const createUserModule = (fastify: FastifyInstance) => {
  fastify.register(async (fastify) => {
    const userService = new UserService();
    
    fastify.post('/users', async (req, res) => {
      return userService.create(req.body);
    });
  });
};

// 4. Middleware/hooks для cross-cutting concerns
fastify.addHook('preHandler', async (request, reply) => {
  // Auth, logging, validation
});

// 5. Layered architecture
// presentation -> application -> domain -> infrastructure

Архитектура на production

В моих проектах я использую гибридный подход:

// Слой Presentation (Fastify Controllers)
export class UserController {
  constructor(private userService: UserService) {}
  
  async create(request, reply) {
    const result = await this.userService.create(request.body);
    reply.send(result);
  }
}

// Слой Application (Use Cases)
export class CreateUserUseCase {
  constructor(private repo: UserRepository) {}
  
  async execute(input: CreateUserInput): Promise<User> {
    const user = new User(input.name, input.email);
    return this.repo.save(user);
  }
}

// Слой Domain (Business Logic)
export class User {
  constructor(readonly name: string, readonly email: string) {
    this.validate();
  }
  
  private validate() {
    if (!this.email.includes('@')) throw new Error('Invalid email');
  }
}

// Слой Infrastructure (Database)
export class UserRepository {
  constructor(private db: Database) {}
  
  async save(user: User): Promise<User> {
    return this.db.users.create(user);
  }
}

Ключевые архитектурные решения

1. Request/Response Flow

HTTP Request
  ↓
Middleware (auth, logging, validation)
  ↓
Controller/Handler
  ↓
Service/UseCase
  ↓
Repository/Database
  ↓
Response Serialization
  ↓
HTTP Response

2. Dependency Injection

class Container {
  resolve(name: string, dependencies: string[]) {
    return new Class(...dependencies.map(d => this.resolve(d)));
  }
}

3. Error Handling

Handler throws Error
  ↓
Error middleware catches
  ↓
Logs error
  ↓
Returns appropriate HTTP response

4. Async Operations

// Fastify and modern frameworks use async/await
async handler(req, res) {
  const result = await db.query();
  return result;
}

Conclusion

На основе анализа:

  • Express — Middleware Chain (просто, но требует структуры)
  • Fastify — Plugin System (модульное, быстро)
  • NestJS — Module + DI (сложно, но структурировано)
  • Hapi — Schema-First (безопасное)
  • Koa — Async-Context (современное)

Все они основаны на:

  1. Request/Response обработке — core functionality
  2. Middleware/Plugin паттернах — расширяемость
  3. Async операциях — для I/O
  4. Dependency Injection — для управления зависимостями
  5. Валидации — для безопасности

Я выбираю Fastify + собственный DI слой, так как получается оптимальный баланс между простотой Express и структурой NestJS.