Главный принцип: slug хранится в данных
Динамический маршрут ([slug] в Next.js или [slug].vue в Nuxt) получает значение из адреса, а сопоставляет его с записью. Если вычислять slug «на лету» из заголовка, то каждая правка заголовка меняет адрес страницы. Надёжнее хранить slug в CMS или в файле данных и менять его осознанно.
Функция по таблице Яндекса
Готовая функция на JavaScript. Подключите её в скрипте импорта или в хуке сохранения записи:
const MAP = {
'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e',
'ё': 'e', 'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k',
'л': 'l', 'м': 'm', 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r',
'с': 's', 'т': 't', 'у': 'u', 'ф': 'f', 'х': 'h', 'ц': 'c',
'ч': 'ch', 'ш': 'sh', 'щ': 'shh', 'ъ': '', 'ы': 'y', 'ь': '',
'э': 'e', 'ю': 'yu', 'я': 'ya',
};
export function yandexSlug(text) {
return [...text.toLowerCase()]
.map((ch) => MAP[ch] ?? ch)
.join('')
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '');
}
Для «Щёлково цех юг» функция даёт shhelkovo-ceh-yug: так же, как генератор. Другие языки и варианты — в статье «Функция транслита на PHP, JavaScript и Python».
Маршруты и генерация страниц
- В Next.js при статической генерации список адресов возвращает
generateStaticParams(App Router) илиgetStaticPaths(Pages Router). В него попадают готовые slug из данных. - В Nuxt список страниц для предварительной генерации собирается из тех же данных.
- Подробнее о динамических маршрутах — в статье «Динамические маршруты в Next.js».
Почему лучше латиница в slug
Русские буквы в адресе кодируются в виде процентов, и параметр маршрута приходит в закодированном виде. Это легко обрабатывать, но неудобно при копировании ссылок: подробнее — в статье «Как Google обрабатывает кириллицу в URL».
Связанные статьи
Связку API и маршрутов описывает статья «ЧПУ в Strapi и Next.js».
Типичные ошибки
- Вычислять slug из заголовка в маршруте при каждом запросе.
- Не фиксировать slug после публикации.
- Допускать пустой slug для заголовков без латиницы.
- Забывать генерировать редиректы при смене slug.
Пошагово: приводим адреса к единому виду
- Определите, где в проекте создаются записи: CMS, скрипт импорта или админка.
- Подключите функцию
yandexSlugв этом месте. - Сохраняйте slug отдельным полем.
- В маршруте ищите запись по slug, а не по заголовку.
- Для старых записей заполните slug одним скриптом.
Разбор заголовка по шагам
Возьмём заголовок «Как выбрать беговые кроссовки» и пройдём путь до адреса. Функция превращает заголовок в slug один раз при сохранении записи.
Заголовок: Как выбрать беговые кроссовки
Без служебных слов: Как выбрать беговые кроссовки
Адрес целиком: kak-vybrat-begovye-krossovki
Адрес короче: kak-vybrat-begovye-krossovki
Режим «Убрать служебные слова» в генераторе делает второй шаг сам. Короткий адрес читается легче и лучше помещается в строку браузера. Ограничения по длине и другие правила составления адреса собраны в статье «Как составить ЧПУ-адрес страницы».
Памятка для редактора
Если в проекте несколько редакторов, дайте им короткую памятку. Достаточно этих правил:
- Slug хранится в данных.
- Функция — по таблице Яндекса.
- Смена slug — с редиректом.
Чек-лист
- Хранить slug в данных.
- Вычислять его при создании записи.
- Использовать одну функцию для всего проекта.
- При смене slug настраивать редирект.
Частые вопросы
Создаёт ли Next.js slug из заголовка?
Нет: адрес берётся из данных, slug нужно хранить вместе с записью.
Где вычислять slug?
В момент создания записи: в хуке CMS или в скрипте импорта.
Что будет, если менять заголовок?
Если slug вычисляется из заголовка на лету, адрес изменится. Лучше хранить slug отдельно.
Какая таблица в функции из статьи?
Таблица Яндекса, та же, что в генераторе на этом сайте.
Проверьте свои заголовки: вставьте их в генератор ЧПУ и посмотрите, как в адресе выглядят слова с этой буквой.