Любое приложение на express
состоит минимум из трёх элементов:
import Express from 'express';
const app = new Express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Example app listening on port 3000!');
});
С первым и последним пунктом всё более-менее понятно, а вот обработчики — это уже интересно. Напомню, что микрофреймворки строятся по схеме: http verb
+ path
+ callback
. В случае express
глагол определяется функцией, которая вызывается на объекте app
. Например если мы хотим определить маршрут GET /
, то для этого необходимо вызывать функцию get
и первым параметром передать в неё строку /
. Таким же образом нужно поступать для любого другого маршрута. Вот список глаголов, которые нас будут интересовать в процессе этого курса:
// И - Идемпотентный
app.head // И
app.get // И
app.post
app.delete // И
// Полное обновление
app.put // И
// Частичное обновление
app.patch
Семантика http
подразумевает, что глаголы get, delete, head и put, являются идемпотентными. Это должно обеспечиваться программистом, который реализует обработчики.
Самая главная и мощная функциональность системы роутинга — это работа с динамическими маршрутами.
Route path: /users/:userId/books/:id
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "id": "8989" }
app.get('/users/:userId/books/:id', (req, res) => {
const { userId, id } = req.params;
});
Для динамических частей используется заполнитель :name
, который состоит из двоеточия и произвольного имени. Express
производит сопоставление актуального запроса со всеми шаблонами в порядке определения и выполняет соответствующие обработчики. Все динамические части маршрута попадают в объект req.params
.
Кроме этого, express
позволяет использовать регулярные выражения прямо в шаблоне:
// abcd, abxcd, abRANDOMcd, ab123cd
app.get('/ab*cd', (req, res) => {
res.send('ab*cd');
});
Честно говоря, за свой многолетний опыт я не припомню ситуацию, когда мне это могло понадобиться. Всегда, если у вас есть возможность управлять урлами, можно сделать хороший вариант на одних плейсхолдерах (заполнителях), без прямого использования регулярных выражений.
У системы маршрутизации есть ещё одна важная задача - генерация ссылок. В стандартной поставке express
такого механизма нет. Это приводит к тому, что люди, незнакомые с концепцией, генерируют адреса в html
, используя строки. Даже существует специальный термин, который называется хардкодинг, при котором прописываются конкретные значения вместо генерации.
<a href=`/posts/${post.id}`>edit</a>
На любом веб-фреймворке, в любом языке так делать нельзя. Если вы измените свои маршруты, то без полной проверки сайта будет невозможно понять что и где сломалось, ведь все ссылки остались старыми. Кроме помощи при отладке и рефакторинге, такой механизм убирает дублирование и позволяет (работает не всегда) изменять маршруты без необходимости переписывать генерацию адресов в html
.
import Express from 'express';
import Router from 'named-routes';
const app = new Express();
const router = new Router();
router.extendExpress(app);
router.registerAppHelpers(app);
app.get('/admin/users/:id', 'admin.user', (req, res, next) => {
//... implementation
// the names can also be accessed here:
const path = app.namedRoutes.build('admin.user', { id: 2 }); // /admin/users/2
// the name of the current route can be found at req.route.name
});
В примере выше был создан именованный маршрут admin.user
. Теперь, где-то в другом обработчике можно строить ссылки используя имя маршрута:
app.get('/users', 'users', (req, res, next) => {
const path = app.namedRoutes.build('admin.user', { id: 2 }); // /admin/users/2
// path содержит путь с которым можно сделать что-то полезное
});
Преимущества:
После долгих раздумий я решил, что в этом курсе, всё же, мы будем хардкодить ссылки. Это связано с тем, что использование соответствующего механизма в express
сильно меняет стандартные интерфейсы, а цель этого курса изучить чистые концепции. В реальной жизни используйте соответствующие расширения.
Каждый определяемый обработчик принимает на вход два параметра: req
и res
. В этом смысле, всё очень похоже на ситуацию с http
модулем с той лишь разницей, что там подобный обработчик один, а здесь на каждый маршрут свой. Request
и Response
предоставляют упрощенный интерфейс. Больше нет необходимости, по крайней мере в простых случаях, пользоваться ими как eventEmitter
. На каждую задачу эти объекты предоставляют метод или свойство.
// GET /users?page=3
app.get('/users', (req, res) => {
console.log(req.query); // { page: 3 }
res.status(200);
res.send(users);
// res.json(users);
});
Пройдёмся по базовым возможностям:
req.query
готовый к обработке query string
, другими словами вам не придётся парсить эти параметры, они уже поступают в виде объекта;res.status(code)
;res.send(data)
. Все необходимые заголовки выставляются автоматически;json
, то express
позволяет это делать без использования дополнительных механизмов. Всё что нужно сделать это вызвать метод res.json(data)
, и данные будут автоматически сериализованы и отправлены клиенту.Вам ответят команда поддержки Хекслета или другие студенты.
Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.
Загляните в раздел «Обсуждение»:
Статья «Ловушки обучения»
Вебинар «Как самостоятельно учиться»
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.
Наши выпускники работают в компаниях:
С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.
Зарегистрируйтесь или войдите в свой аккаунт