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

Зачем нужен Express?

1.0 Junior🔥 111 комментариев
#Soft Skills и рабочие процессы

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Express.js: назначение, архитектура и использование

Express.js — это минималистичный и мощный фреймворк для Node.js, который упрощает создание серверных приложений, REST API и веб-приложений. Это один из самых популярных фреймворков в Node.js экосистеме.

Что такое Express

Express предоставляет удобный набор инструментов для:

  • Обработки HTTP запросов
  • Маршрутизации (routing)
  • Управления middleware
  • Обработки ошибок
  • Сервирования статичных файлов
// Без Express (нативный Node.js)
const http = require('http');

const server = http.createServer((req, res) => {
  // Всё нужно писать вручную: парсинг URL, методов и т.д.
  if (req.method === 'GET' && req.url === '/users') {
    const users = [{ id: 1, name: 'Alice' }];
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(users));
  } else if (req.method === 'POST' && req.url === '/users') {
    let body = '';
    req.on('data', chunk => body += chunk);
    req.on('end', () => {
      const user = JSON.parse(body);
      // Сохранить пользователя
      res.writeHead(201, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify(user));
    });
  } else {
    res.writeHead(404);
    res.end('Not Found');
  }
});

server.listen(3000);
// Много boilerplate кода, сложно масштабировать

// С Express (значительно проще)
const express = require('express');
const app = express();

app.use(express.json()); // Парсинг JSON автоматически

app.get('/users', (req, res) => {
  const users = [{ id: 1, name: 'Alice' }];
  res.json(users); // JSON парсинг встроен
});

app.post('/users', (req, res) => {
  const user = req.body; // Автоматически распарсен
  // Сохранить пользователя
  res.status(201).json(user);
});

app.listen(3000);
// Чистый, понятный код

Основные возможности Express

1. Маршрутизация (Routing)

const express = require('express');
const app = express();

// GET запросы
app.get('/users', (req, res) => {
  res.json({ message: 'Get all users' });
});

app.get('/users/:id', (req, res) => {
  const { id } = req.params;
  res.json({ message: `Get user ${id}` });
});

// POST запросы
app.post('/users', (req, res) => {
  const { name, email } = req.body;
  res.status(201).json({ id: 1, name, email });
});

// PUT запросы
app.put('/users/:id', (req, res) => {
  const { id } = req.params;
  const { name, email } = req.body;
  res.json({ id, name, email });
});

// DELETE запросы
app.delete('/users/:id', (req, res) => {
  const { id } = req.params;
  res.json({ message: `User ${id} deleted` });
});

// Query параметры
app.get('/search', (req, res) => {
  const { q, limit } = req.query; // ?q=test&limit=10
  res.json({ query: q, limit });
});

2. Middleware (обработчики)

Middleware — это функция, которая обрабатывает запрос перед отправкой ответа:

// Логирование
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next(); // Передать управление следующему middleware
});

// Парсинг JSON
app.use(express.json());

// Парсинг URL encoded
app.use(express.urlencoded({ extended: true }));

// Сервирование статичных файлов
app.use(express.static('public'));

// Проверка авторизации
app.use('/admin', (req, res, next) => {
  if (!req.headers.authorization) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  next();
});

// Middleware может быть на конкретном маршруте
const authenticate = (req, res, next) => {
  // Проверить токен
  next();
};

app.post('/posts', authenticate, (req, res) => {
  // Только авторизованные пользователи могут создавать посты
  res.json({ message: 'Post created' });
});

// Цепочка middleware
app.put('/users/:id',
  authenticate,
  validateUserData,
  updateUser
);

3. Обработка ошибок

// Error handling middleware (4 параметра!)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Something went wrong' });
});

// Должен быть в конце app.use

// Пример использования
app.get('/users/:id', async (req, res, next) => {
  try {
    const user = await getUserFromDB(req.params.id);
    if (!user) {
      return res.status(404).json({ error: 'User not found' });
    }
    res.json(user);
  } catch (error) {
    next(error); // Передать ошибку в error handler
  }
});

4. Router (для большых приложений)

// users.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.json([
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' }
  ]);
});

router.post('/', (req, res) => {
  const user = req.body;
  res.status(201).json(user);
});

router.get('/:id', (req, res) => {
  res.json({ id: req.params.id, name: 'User' });
});

router.put('/:id', (req, res) => {
  res.json({ ...req.body, id: req.params.id });
});

router.delete('/:id', (req, res) => {
  res.json({ message: 'Deleted' });
});

module.exports = router;

// app.js
const express = require('express');
const usersRouter = require('./routes/users');
const postsRouter = require('./routes/posts');

const app = express();

app.use(express.json());
app.use('/api/v1/users', usersRouter);
app.use('/api/v1/posts', postsRouter);

app.listen(3000);

Архитектурный паттерн: MVC

Express часто используется с MVC (Model-View-Controller) паттерном:

// routes/users.js
const express = require('express');
const usersController = require('../controllers/users');

const router = express.Router();

router.get('/', usersController.getAll);
router.get('/:id', usersController.getById);
router.post('/', usersController.create);
router.put('/:id', usersController.update);
router.delete('/:id', usersController.delete);

module.exports = router;

// controllers/users.js
const User = require('../models/User');

const getAll = async (req, res, next) => {
  try {
    const users = await User.findAll();
    res.json(users);
  } catch (error) {
    next(error);
  }
};

const getById = async (req, res, next) => {
  try {
    const user = await User.findById(req.params.id);
    if (!user) {
      return res.status(404).json({ error: 'Not found' });
    }
    res.json(user);
  } catch (error) {
    next(error);
  }
};

const create = async (req, res, next) => {
  try {
    const user = await User.create(req.body);
    res.status(201).json(user);
  } catch (error) {
    next(error);
  }
};

// ... update, delete

module.exports = { getAll, getById, create };

// models/User.js
const db = require('../db');

class User {
  static async findAll() {
    const [users] = await db.query('SELECT * FROM users');
    return users;
  }
  
  static async findById(id) {
    const [users] = await db.query('SELECT * FROM users WHERE id = ?', [id]);
    return users[0];
  }
  
  static async create(data) {
    const { name, email } = data;
    const [result] = await db.query(
      'INSERT INTO users (name, email) VALUES (?, ?)',
      [name, email]
    );
    return { id: result.insertId, name, email };
  }
  
  // ... update, delete
}

module.exports = User;

// app.js
const express = require('express');
const usersRouter = require('./routes/users');

const app = express();

app.use(express.json());
app.use('/api/v1/users', usersRouter);

app.listen(3000);

Зачем Express нужен Frontend разработчику

1. Локальная разработка (Dev server)

// server.js
const express = require('express');
const path = require('path');

const app = express();

// Сервировать React приложение
app.use(express.static(path.join(__dirname, 'build')));

// API mock
app.get('/api/v1/users', (req, res) => {
  res.json([
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' }
  ]);
});

// SPA fallback (для React Router)
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(3000);

2. Mock API для тестирования

// Во время разработки фронта часто бэк не готов
// Express помогает создать mock API

app.get('/api/v1/posts', (req, res) => {
  res.json([
    { id: 1, title: 'Post 1', content: 'Content 1' },
    { id: 2, title: 'Post 2', content: 'Content 2' }
  ]);
});

app.post('/api/v1/posts', (req, res) => {
  const { title, content } = req.body;
  res.status(201).json({
    id: 3,
    title,
    content,
    createdAt: new Date()
  });
});

3. BFF (Backend For Frontend)

Иногда фронт-разработчик пишет небольшой сервер для агрегации API:

// вместо 3 запросов на фронте, делаем 1 на BFF
app.get('/api/v1/dashboard', async (req, res) => {
  try {
    const users = await fetch('https://api.internal.com/users');
    const posts = await fetch('https://api.internal.com/posts');
    const comments = await fetch('https://api.internal.com/comments');
    
    res.json({
      users: await users.json(),
      posts: await posts.json(),
      comments: await comments.json()
    });
  } catch (error) {
    res.status(500).json({ error: 'Failed' });
  }
});

Популярные middleware и расширения

const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const compression = require('compression');
const rateLimit = require('express-rate-limit');

const app = express();

// CORS
app.use(cors({
  origin: 'https://example.com',
  credentials: true
}));

// Security headers
app.use(helmet());

// HTTP logging
app.use(morgan('combined'));

// Compression (gzip)
app.use(compression());

// Rate limiting
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100
});
app.use('/api/', limiter);

// Body parsing
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ limit: '10mb', extended: true }));

Альтернативы Express

// Fastify (быстрее, современнее)
const fastify = require('fastify')();
fastify.get('/users', async () => {
  return { users: [] };
});
await fastify.listen({ port: 3000 });

// Koa (меньше middleware в коробке, более гибкий)
const Koa = require('koa');
const app = new Koa();
app.use(ctx => {
  ctx.body = { message: 'Hello' };
});
app.listen(3000);

// Next.js (для React приложений с SSR)
// Встроенный Express внутри, проще использовать

Простой пример полного приложения

const express = require('express');
const app = express();

app.use(express.json());
app.use(morgan('dev'));
app.use(cors());

// Routes
app.get('/api/v1/users', (req, res) => {
  res.json([{ id: 1, name: 'Alice' }]);
});

app.post('/api/v1/users', (req, res) => {
  const { name } = req.body;
  res.status(201).json({ id: 2, name });
});

// Error handling
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: 'Internal error' });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Итог

Express нужен для:

  • Быстрого создания REST API
  • Простой маршрутизации
  • Middleware (логирование, авторизация, валидация)
  • Обработки ошибок
  • Сервирования статичных файлов

Для фронт-разработчиков:

  • Mock API во время разработки
  • BFF (Backend For Frontend)
  • Локальная разработка с реалистичным сервером
  • Простая альтернатива созданию полноценного backend

Плюсы:

  • Минималистичный (не навязывает структуру)
  • Огромная экосистема middleware
  • Очень популярен (много примеров и help)
  • Легко выучить и использовать

Express — де-факто стандартный выбор для Node.js приложений в 2024 году.