Структура проекта и что дальше

Собираем знания воедино: как устроен настоящий проект и куда двигаться после курса.

Почему не всё в одном файле

Маленький сервер помещается в index.js. Но как только маршрутов и логики становится много, один файл превращается в кашу. Реальные проекты разбивают на слои с чёткой ответственностью.

Типичная структура

my-api/
├── package.json
├── .env                # секреты (не в git)
├── .gitignore
└── src/
    ├── index.js        # запуск сервера
    ├── app.js          # настройка Express и middleware
    ├── routes/         # описание маршрутов
    │   └── tasks.js
    ├── controllers/    # обработчики запросов
    │   └── tasks.js
    ├── services/       # бизнес-логика
    │   └── tasks.js
    └── models/         # работа с данными/БД
        └── task.js

Слои и их роли

СлойОтвечает за
routesкакой URL → какой обработчик
controllersпринять req, вернуть res
servicesбизнес-логику (правила, расчёты)
modelsчтение и запись данных в БД

Смысл разделения: каждый файл занят одним делом, код легко искать, тестировать и менять. Маршрут не лезет в SQL, а модель не знает про HTTP.

Выносим маршруты в отдельный модуль

Express позволяет описать группу маршрутов в отдельном файле через express.Router() и подключить в основном приложении:

// routes/tasks.js
const express = require("express");
const router = express.Router();

router.get("/", (req, res) => res.json([]));
router.post("/", (req, res) => res.status(201).json(req.body));

module.exports = router;

// app.js
const tasksRouter = require("./routes/tasks");
app.use("/tasks", tasksRouter); // все маршруты под /tasks

Это прямое применение модулей из раздела 2: каждый кусок в своём файле, связаны через require/module.exports.

Группировка данных — обычный JS

Бизнес-логика в services — это чистый JavaScript. Например, сгруппировать задачи по статусу:

const tasks = [
  { id: 1, title: "Хлеб", done: false },
  { id: 2, title: "Врач", done: true },
  { id: 3, title: "Цветы", done: false }
];

const grouped = { done: [], pending: [] };
for (const t of tasks) {
  if (t.done) grouped.done.push(t.title);
  else grouped.pending.push(t.title);
}

console.log("Выполнено:", grouped.done);
console.log("В работе:", grouped.pending);

Вывод:

Выполнено: [ 'Врач' ]
В работе: [ 'Хлеб', 'Цветы' ]

Что изучать дальше

  • TypeScript — типы для надёжного серверного кода (это снимает целый класс ошибок).
  • NestJS / Fastify — более структурированные фреймворки поверх Node.
  • Тесты — Jest или встроенный node:test для проверки логики.
  • Аутентификация — JWT, сессии, хеширование паролей (bcrypt).
  • Деплой — Docker, переменные окружения, процесс-менеджеры (pm2), облака.

Итог

  • Реальный проект разбивают на слои: routes, controllers, services, models.
  • Каждый слой отвечает за одно — код проще искать, тестировать и менять.
  • express.Router() выносит группы маршрутов в отдельные модули.
  • Дальше: TypeScript, фреймворки (NestJS), тесты, аутентификация, деплой.
Проверьте себя
1. За что отвечает слой models в типичной структуре Node-проекта?
AЗа маршрутизацию URL
BЗа чтение и запись данных в БД
CЗа HTTP-заголовки
DЗа запуск сервера
2. Что позволяет express.Router()?
AУскорить сервер
BВынести группу маршрутов в отдельный модуль и подключить её
CЗаменить middleware
DПодключиться к БД
3. Что из перечисленного — логичный следующий шаг после основ Node?
AОтказаться от npm
BTypeScript, тесты, фреймворки вроде NestJS и деплой
CПисать всё в одном файле
DВернуться к колбэкам
Поддержать проект