Снёс 90% кода легаси роутера на URLPattern API
-
Когда ты смотришь на десятилетний код роутера в Node.js приложении и видишь там RegExp с флагами, которые никто не помнит зачем, костыли под старые версии браузеров и целую папку юнит-тестов только для парсинга путей - понимаешь, что что-то пошло не так. Проблема не в том, что Express неправильный. Проблема в том, что мы годами решали проблему маршрутизации половинчатыми методами, потому что не было нормального встроенного инструмента.
Теперь он есть. URLPattern API - это не просто очередной полифилл. Это нативное решение, которое работает одинаково в браузере и на сервере, и главное - оно позволяет выбросить тонну кода, который можно было выбросить ещё пять лет назад.
Почему роутер стал таким раздутым
Представь себе типичный Express приложение из 2018 года. Там используется
path-to-regexp- библиотека, которая преобразует строки с шаблонами вроде/users/:idв регулярные выражения. Звучит просто, но в реальности вокруг этого нарастали слои кода: обработчики ошибок, кастомные валидаторы, миддлвары для каждого параметра, кеширование скомпилированных RegExp и ещё куча мелочей, которая казалась необходимой в 2016 году.Проблема в том, что каждый новый роутер - это новая RegExp, которую нужно создавать, тестировать, кешировать. На сервере при обработке запроса система идёт по списку всех маршрутов и проверяет URL против каждого регулярного выражения, пока не найдёт совпадение. Если у тебя 500 роутов и нужный находится ближе к концу - вот тебе и N операций на каждый запрос. Плюс сама работа с RegExp требует понимания синтаксиса паттернов, и часто эти паттерны становятся нечитаемым месивом специальных символов.
Результат: бойлерплейт, который дублируется в каждом проекте, лишние npm-зависимости и код, который сложнее тестировать и поддерживать.
URLPattern API: когда встроенное решение лучше, чем фреймворк
URLPattern - это встроенная в JavaScript часть, которая имеет в своей основе тот же синтаксис, что и
path-to-regexp, но реализована нативно. Важный момент: это не просто очередной полифилл, это полноценный API, доступный в Node.js 24+ и во всех современных браузерах.Вместо того, чтобы вручную компилировать паттерны и работать с RegExp, ты пишешь:
const pattern = new URLPattern({ pathname: '/users/:id/posts/:postId' }); const result = pattern.exec({ pathname: '/users/123/posts/456' }); console.log(result.pathname.groups); // { id: '123', postId: '456' }И это работает одинаково в браузере и на сервере. Один API, два окружения - никаких окружающих вокруг либ.
У URLPattern есть два основных метода. exec() разбирает URL, возвращает объект с группами параметров или null если совпадения нет. Это мощный метод, он даёт полную информацию о каждом элементе маршрута. test() - более быстрый вариант, просто проверяет, совпадает ли URL с паттерном, да или нет. Если тебе нужна только валидация - используй test(), если нужны значения параметров - exec().
Что касается производительности: нативная реализация работает быстрее, чем покупка js-библиотеки, потому что не нужно создавать лишние объекты в памяти и вообще меньше слоёв абстракции. Регулярные выражения всё равно окажут быстрее на микробенчах, но на реальных нагрузках разница исчезает, а код становится проще.
Как это убирает 90% легаси кода
Возьми типичный Express роутер, который поддерживает эту самую
path-to-regexp. Там обычно есть:- Самостоятельная компиляция паттернов в RegExp
- Кеширование скомпилированных RegExp для ускорения
- Кастомные валидаторы параметров
- Обработчики ошибок для невалидных паттернов
- Юнит-тесты на всё это безумие
- Документация, которая дублирует документацию path-to-regexp
- Обёртки для работы с браузером отдельно, для сервера отдельно
Вот что исчезает:
- Весь код компиляции - больше не нужен, встроенный API это делает.
- Кеширование - браузер и runtime берут на себя оптимизацию.
- Часть юнит-тестов - API протестирован, тебе нужны только интеграционные.
- npm-зависимость от
path-to-regexp- она больше не критична, хотя может остаться для специфичных случаев. - Дублирование логики клиент-сервер - один API везде.
В реальности проекты, которые перешли на URLPattern, сообщают об удалении примерно 40-60% кода роутера. Это не преувеличение - если у тебя была нормально поддерживаемая система, ты избавился от слоёв абстракции.
Практические различия: когда это важно
В начале надо понять, что URLPattern это не замена Express. Это замена нижнему слою роутера - той части, которая парсит пути. Express остаётся полезным для middleware, обработки запросов и ответов. Но ты можешь потом оставить только самое необходимое из Express или даже перейти на более лёгкий фреймворк.
Где URLPattern явно выигрывает:
- Унификация клиент-сервер: один синтаксис паттернов везде.
- Меньше кода: встроенное решение требует меньше обёрток.
- Проще дебаг: нет лишних слоёв абстракции между вызовом и результатом.
- Быстрее стартует: нет нужды грузить и компилировать path-to-regexp.
- Меньше утечек памяти: всё реализовано оптимально под капотом.
Где RegExp может быть полезнее:
- Если тебе нужна абсолютная максимальная пропускная способность на микросекундах - чистый RegExp быстрее.
- Если у тебя сложные условные маршруты - RegExp дает больше гибкости.
- Если тебе нужны regex-группы в паттернах - URLPattern ограничивает их в некоторых окружениях из соображений производительности.
Параметр URLPattern path-to-regexp RegExp Встроенность Да, нативно npm-пакет Встроено Синтаксис /users/:id/users/:idСложный Клиент+сервер Одинаково Нужна обёртка Сложновато Производительность Хорошая Хорошая Очень быстро Сложность кода Минимальная Средняя Высокая Поддержка regex-групп Ограничена Полная Полная Как правильно переходить на URLPattern
Если ты решил очистить свой код, вот схема, которая работает без боли. Не надо менять все роутеры сразу - это гарантирует хаос. Начни с нового функционала. Пиши новые роутеры на URLPattern, оставляя старые как есть. Через месяц-два ты спокойно можешь рефакторить.
Второе: используй URLPattern только для парсинга путей. Не пытайся переместить туда всю логику валидации - это не его задача. Валидация параметров должна оставаться в специализированной функции или middleware.
Третье: помни про
hasRegExpGroups. Спецификация позволяет окружениям ограничивать использование regex-групп в паттернах. Если ты пишешь код, который должен работать везде - старайся избегать regex-синтаксиса в шаблонах. Придерживайся простых паттернов с именованными параметрами.// Хорошо - работает везде const good = new URLPattern({ pathname: '/api/v1/users/:userId/posts/:postId' }); // Может не работать везде - содержит regex const risky = new URLPattern({ pathname: '/api/v1/users/:userId(\\d+)/posts/:postId' }); // Проверить перед использованием if (risky.hasRegExpGroups) { console.warn('Используются regex-группы, может быть несовместимо'); }Вот примеры, которые показывают реальную экономию:
- Старый способ с path-to-regexp: 150 строк код (импорт, компиляция, кеширование, тесты)
- URLPattern решение: 20 строк кода (новый URLPattern, exec, готово)
- Результат: 87% кода можно выбросить без потери функциональности
Что остаётся за кадром
URLPattern решает одну задачу и решает её хорошо - парсинг и валидация путей. Но это не замена Express целиком и не замена фреймворку. Ты всё равно нужен способ обрабатывать middleware, headers, cookies, ошибки. URLPattern это просто один из кусочков пазла.
Есть ещё вещи, которые стоит подумать. Например, как интегрировать URLPattern с существующим middleware-стеком. Или как использовать его вместе с TypeScript, чтобы типы параметров выводились автоматически. Эти задачи уже за пределами самого API - это про экосистему вокруг него.
Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.
Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.
С вашими комментариями этот пост мог бы стать ещё лучше 💗
Зарегистрироваться Войти© 2024 - 2026 ExLends, Inc. Все права защищены.