Express 3.x — частые вопросы и миграция

Этот справочник нужен для разбора приложения на Express 3.x. Его сигнатуры и встроенные модули Connect отличаются от поддерживаемых версий: Express 2.x и 3.x больше не получают исправлений. Примеры старых зависимостей не предназначены для нового публичного сервера. Для переноса используйте миграцию 3 → 4 и затем 4 → 5.

Как создавать модели?

В Express нет средств для работы с базами данных, это полностью может быть возложено на сторонние модули, что даёт возможность работать практически с любыми базами данных.

Как сделать вход и проверку прав?

Express маршрутизирует запросы, но сам не определяет пользователей и права. Не копируйте демонстрационную проверку логина/пароля как production-систему. Отделите подтверждение личности от проверки доступа к конкретному ресурсу; настройте TLS, сессию и защиту от перебора. Для серверных сессий ознакомьтесь с express-session, включая ограничения MemoryStore.

Какой шаблонизатор использует Express?

В старой документации требуется соглашение вызова (path, options, callback); зарегистрировать движок можно через app.engine(). Express не навязывает один шаблонизатор. Архивный Jade и его современное продолжение разобраны в отдельном руководстве. Не отдавайте непроверенные пользовательские значения как HTML.

Какова правильная структура приложения?

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

Старый список ссылался на route-separation, route-map, неработающий route-loading, MVC и расширения express-resource/namespace. Для чтения кода той версии используйте примеры релиза 3.0.0beta7; для нового приложения — текущий генератор как заготовку, а не обязательную архитектуру.

Как отдавать статику из нескольких директорий?

Обычно можно использовать любую прослойку несколько раз внутри приложения. При следующей конфигурации по запросу "GET /javascripts/jquery.js" сначала будет проверяться файл "./public/javascripts/jquery.js", а потом, если файл не обнаружится, то следующая прослойка будет проверять "./files/javascripts/jquery.js".

app.use(express.static('public'));
app.use(express.static('files'));

Как можно задать префикс для отдачи статики?

Connect умеет "монтировать" прослойки, что позволяет задавать "префикс" пути, по которому будет вызвана прослойка, при этом префикс с точки зрения самой прослойки не будет являться частью пути. Допустим, есть запрос "GET /files/javascripts/jquery.js", можно смонтировать прослойку с префиксом "/files", показывая "/javascripts/jquery.js" как req.url, что позволяет прослойке отдавать файл:

app.use('/files', express.static('public'));

Как мигрировать с Express 2.x и 3.x?

Исходный ответ обещал долгую поддержку 2.x; это утверждение больше неверно. Обе ветки не поддерживаются. Сначала найдите использованные middleware и старые сигнатуры, покройте маршруты успешными/ошибочными проверками, затем проходите несовместимые изменения последовательно: исторические различия 2 → 3, 3 → 4, 4 → 5. Простая замена номера пакета не завершает миграцию.

Как обрабатывать ошибку 404?

В Express 404 не является результатом ошибки, поэтому прослойка error-handler не перехватывает 404, это происходит потому, что 404 свидетельствует о том, что приложению нечего делать - иными словами, Express выполнил все прослойки / маршруты и обнаружил, что ни один из них не ответил. Всё, что нужно сделать - это добавить слой в самом низу, который бы обрабатывал 404:

app.use(function(req, res, next){
  res.status(404).send('Здесь никого нет!');
});

Как в Express настроить обработчик ошибок?

Прослойка обработки ошибок определяется как и другие прослойки, однако она должна быть определена с четырьмя аргументами, вот так (err, req, res, next):

app.use(function(err, req, res, next){
  console.error(err.stack);
  if (res.headersSent) return next(err);
  res.status(500).send('Что-то сломалось!');
});

Подробнее тут обработка ошибок.

Как отдать готовый HTML?

Шаблонизация не нужна, если файл уже готов. В Express 3 встречается res.sendfile(), в современном — res.sendFile(). Используйте контролируемый абсолютный путь или параметр root, не собирайте путь из непроверенного URL. Для папки публичных файлов подходит express.static().

Насколько велика кодовая база Express?

Исходный FAQ приводил 932 SLOC для Express 3.0.0, 267 строк обязательной части Connect и 1143 строки дополнительных middleware. Это исторический подсчёт, а не характеристики текущего релиза. При выборе стека важнее проверить поддерживаемость зависимостей, требуемые middleware, нагрузку и покрытие своих маршрутов.

Исходная документация: © 2012 TJ Holowaychuk; русский перевод опубликован JSman. Технические уточнения обозначены отдельно от сигнатур Express 3.

Заметки и перевод: @jsmarkus