SEO в Nuxt: useSeoMeta и useHead
SSR отдаёт готовый HTML, но без правильных мета-тегов он бесполезен для SEO: useSeoMeta задаёт title, описание и превью для соцсетей.
Суть: useSeoMeta — типобезопасный композабл для SEO-мета-тегов (title, description, Open Graph). useHead — общий инструмент для любых тегов head. При SSR теги попадают в исходный HTML, поэтому видны поисковикам и ботам соцсетей.
Мы начали курс с того, что SSR нужен ради SEO. Но сам по себе серверный HTML — это полдела. Поисковику и соцсетям нужны правильные мета-теги: заголовок страницы, описание, картинка превью. Без них даже идеально отрендеренная страница плохо индексируется и некрасиво выглядит при шаринге в мессенджер.
Современный и рекомендуемый способ — useSeoMeta. Это плоский типобезопасный API специально для SEO:
<script setup>
useSeoMeta({
title: "Каталог книг — Мой магазин",
description: "Большой выбор книг с доставкой",
ogTitle: "Каталог книг",
ogDescription: "Большой выбор книг с доставкой",
ogImage: "/og/catalog.png",
})
</script>
Для динамических страниц мета-теги строят из данных. На странице товара заголовок берут из самого товара — и поскольку это происходит при SSR, корректный <title> уже есть в исходном HTML:
<script setup>
const { data: product } = await useFetch("/api/products/" + id)
useSeoMeta({
title: () => product.value.name + " — Магазин",
description: () => product.value.shortDescription,
})
</script>
useHead — более общий инструмент: им добавляют любые теги <head> (например, link, script, canonical). Правило простое: для SEO-полей берите useSeoMeta, для всего остального — useHead.
Зачем теги при SSR
запрос -> SSR рендерит страницу + useSeoMeta
|
v
HTML с <title>, <meta description>, og:* УЖЕ внутри
|
+-- поисковик читает -> индексирует корректно
+-- бот мессенджера читает og:* -> красивое превью
Безопасность серверной части — это не один приём, а слоёная защита. Нижний слой — валидация и санитизация любого входа, чтобы кривые или вредоносные данные не дошли до логики. Слой выше — аутентификация (кто этот пользователь) и авторизация (что ему можно), которые удобно централизовать в серверном middleware. Поверх — ограничение частоты запросов от одного клиента, чтобы эндпоинт нельзя было завалить перебором. И наконец, секреты живут только на сервере и никогда не пересекают границу в браузер. Ни один из слоёв не заменяет другой; вместе они и составляют надёжный бэкенд.
Как работает под капотом
За тегами head в Nuxt стоит библиотека Unhead. useSeoMeta — это удобная обёртка с типами поверх неё: вы пишете плоские поля (ogImage вместо ручного <meta property="og:image">), а Unhead собирает корректные теги. При SSR они рендерятся прямо в <head> исходного HTML — поэтому доступны ботам, не исполняющим JS. При клиентской навигации теги реактивно обновляются. Функции-геттеры (() => ...) делают теги реактивными к данным.
Смоделируем сборку мета-тегов из плоского объекта — упрощённую логику useSeoMeta:
// Плоские SEO-поля -> теги для <head>.
function buildMeta(seo) {
const tags = [];
if (seo.title) tags.push("<title>" + seo.title + "</title>");
if (seo.description)
tags.push('<meta name="description" content="' + seo.description + '">');
if (seo.ogTitle)
tags.push('<meta property="og:title" content="' + seo.ogTitle + '">');
if (seo.ogImage)
tags.push('<meta property="og:image" content="' + seo.ogImage + '">');
return tags.join("\n");
}
const product = { name: "Книга про Vue", shortDescription: "Лучший гид по Vue" };
const head = buildMeta({
title: product.name + " — Магазин",
description: product.shortDescription,
ogTitle: product.name,
ogImage: "/og/book.png",
});
console.log("В <head> попадёт:\n" + head);
Попробуй сам ▶ — плоские поля превращаются в готовые теги. При SSR эта разметка уже в исходном HTML, и её видят боты.
Частые ошибки
- Ставить мета-теги только на клиенте. Если задать их после монтирования, бот без JS их не увидит. Делайте при SSR.
- Забывать Open Graph. Без
og:*ссылка в мессенджере выглядит голо, без картинки и описания. - Одинаковый title на всех страницах. Уникальный заголовок на страницу — база SEO.
Best practices
- SEO-поля — через
useSeoMeta; прочие теги head — черезuseHead. - На динамических страницах стройте теги из данных через геттеры
() => .... - Всегда задавайте Open Graph (
ogTitle,ogDescription,ogImage) для красивого шаринга.
Итог: SSR даёт HTML, а useSeoMeta наполняет его правильными мета-тегами, видимыми поисковикам и соцсетям при первом же запросе. Дальше — стратегии рендеринга и подготовка к деплою.