Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

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

Express не создаёт папки за вас: всё можно написать в одном файле. Но когда маршрутов становится больше десятка, такой файл трудно читать. Поэтому проект раскладывают по папкам, где у каждой части своя роль.

Структура блога

Так будет выглядеть проект к середине курса:

blog/
├── package.json
├── .env                  настройки, не попадают в Git
├── src/
│   ├── app.js            создаёт приложение и подключает всё остальное
│   ├── server.js         запускает сервер
│   ├── routes/
│   │   └── posts.js      адреса раздела статей
│   ├── controllers/
│   │   └── postsController.js   функции-обработчики
│   ├── models/
│   │   └── post.js       работа с данными
│   └── middleware/
│       └── requireAuth.js
├── views/                шаблоны HTML-страниц
│   └── posts/
│       └── index.ejs
├── public/               CSS, картинки, скрипты для браузера
│   └── css/style.css
└── test/                 автотесты

Папки views/ и public/ лежат в корне: Express по умолчанию ищет шаблоны в views/ относительно папки, из которой запущен сервер.

Роли папок

Папка или файлЧто внутри
src/app.jsНастройка приложения: middleware, маршруты, обработка ошибок
src/server.jsТолько запуск: app.listen()
src/routes/Какой адрес какой функцией обрабатывается
src/controllers/Что делать с запросом: получить данные, ответить
src/models/Чтение и запись данных
views/Шаблоны страниц
public/Файлы, которые браузер получает как есть

Разделяем app.js и server.js

Создайте файл src/app.js, перенесите в него приложение и экспортируйте его:

// src/app.js
import express from 'express';
 
const app = express();
 
app.get('/', (req, res) => {
  res.send('Привет от блога!');
});
 
export default app;

А src/server.js теперь только импортирует приложение и запускает его:

// src/server.js
import app from './app.js';
 
const PORT = 3000;
 
app.listen(PORT, () => {
  console.log(`Сервер запущен: http://localhost:${PORT}`);
});

Команда npm run dev работает как раньше: http://localhost:3000 показывает то же приветствие. Зато приложение из app.js теперь можно импортировать в тестах, не запуская настоящий сервер, — это пригодится в уроке о тестировании.

Как файлы связаны

Запрос проходит путь сверху вниз: server.js запускает приложение из app.js, app.js передаёт запрос в нужный файл из routes/, маршрут вызывает функцию из controllers/, контроллер берёт данные из models/ и отдаёт страницу по шаблону из views/. Каждое звено появится в своём уроке.

Частая ошибка

В ES-модулях путь к своему файлу пишется полностью, с расширением: import app from './app.js'. Запись './app' без .js работает в некоторых сборщиках, но Node.js на ней остановится с ошибкой ERR_MODULE_NOT_FOUND.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.