SEO и Meta

Улучшите SEO вашего приложения Nuxt с помощью мощных head-конфига, композаблов и компонентов.

Nuxt head tag management is powered by Unhead. It provides sensible defaults, several powerful composables and numerous configuration options to manage your app's head and SEO meta tags.

Nuxt Config

Providing an app.head property in your nuxt.config.ts allows you to statically customize the head for your entire app.

This method does not allow you to provide reactive data. We recommend using useHead() in app.vue.

It's good practice to set tags here that won't change such as your site title default, language and favicon.

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      title: 'Nuxt', // default fallback title
      htmlAttrs: {
        lang: 'en',
      },
      link: [
        { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
      ]
    }
  }
})

You can also provide any of the keys listed below in Types.

Defaults Tags

Some tags are provided by Nuxt by default to ensure your website works well out of the box.

  • viewport: width=device-width, initial-scale=1
  • charset: utf-8

While most sites won't need to override these defaults, you can update them using the keyed shortcuts.

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      // update Nuxt defaults
      charset: 'utf-16',
      viewport: 'width=device-width, initial-scale=1, maximum-scale=1',
    }
  }
})

useHead

The useHead composable function supports reactive input, allowing you to manage your head tags programmatically.

app.vue
<script setup lang="ts">
useHead({
  title: 'Мое приложение',
  meta: [
    { name: 'description', content: 'Мой невероятный сайт.' }
  ],
  bodyAttrs: {
    class: 'test'
  },
  script: [ { innerHTML: 'console.log(\'Привет, мир!\')' } ]
})
</script>

Мы рекомендуем обратить внимание на useHead и useHeadSafe композаблы.

useSeoMeta

The useSeoMeta composable lets you define your site's SEO meta tags as an object with full type safety.

Это поможет вам избежать опечаток и распространенных ошибок, например, использования name вместо property.

app.vue
<script setup lang="ts">
useSeoMeta({
  title: 'Мой невероятный сайт',
  ogTitle: 'Мой невероятный сайт',
  description: 'Это мой невероятный сайт, позвольте мне рассказать вам о нем.',
  ogDescription: 'Это мой невероятный сайт, позвольте мне рассказать вам о нем.',
  ogImage: 'https://example.com/image.png',
  twitterCard: 'summary_large_image',
})
</script>
Узнать больше Docs > API > Composables > Use Seo Meta.

Компоненты

While using useHead is recommended in all cases, you may have a personal preference for defining your head tags in your template using components.

Nuxt предоставляет компоненты <Title>, <Base>, <NoScript>, <Style>, <Meta>, <Link>, <Body>, <Html> и <Head>, чтобы вы могли напрямую взаимодействовать с мета-данными в шаблоне вашего компонента. Note the capitalization of these components ensuring we don't use invalid native HTML tags.

<Head> и <Body> могут принимать вложенные мета-теги (из эстетических соображений), но это не влияет на то, где именно вложенные мета-теги будут отображаться в конечном HTML.

app.vue
<script setup lang="ts">
const title = ref('Привет, мир!')
</script>

<template>
  <div>
    <Head>
      <Title>{{ title }}</Title>
      <Meta name="description" :content="title" />
      <Style>
      body { background-color: green; }
      </Style>
    </Head>

    <h1>{{ title }}</h1>
  </div>
</template>

It's suggested to wrap your components in either a <Head> or <Html> components as tags will be deduped more intuitively.

Типы

Ниже приведены нереактивные типы, используемые для useHead, app.head и компонентов.

interface MetaObject {
  title?: string
  titleTemplate?: string | ((title?: string) => string)
  templateParams?: Record<string, string | Record<string, string>>
  base?: Base
  link?: Link[]
  meta?: Meta[]
  style?: Style[]
  script?: Script[]
  noscript?: Noscript[];
  htmlAttrs?: HtmlAttributes;
  bodyAttrs?: BodyAttributes;
}

Более подробную информацию о типах см. в @unhead/vue.

Возможности

Реактивность

Реактивность поддерживается для всех свойств путем предоставления вычисляемого значения (computed), геттера или реактивного объекта.

<script setup lang="ts">
const description = ref('Мой невероятный сайт.')

useHead({
  meta: [
    { name: 'description', content: description }
  ],
})
</script>

Шаблон названия

Вы можете использовать опцию titleTemplate, чтобы предоставить динамический шаблон для настройки заголовка вашего сайта. Например, вы можете добавить название вашего сайта в заголовок каждой страницы.

titleTemplate может быть либо строкой, где %s заменяется на заголовок, либо функцией.

Если вы хотите использовать функцию (для полного контроля), то ее нельзя задавать в файле nuxt.config. Вместо этого рекомендуется задать ее в файле app.vue, где она будет применяться ко всем страницам вашего сайта:

<script setup lang="ts">
useHead({
  titleTemplate: (titleChunk) => {
    return titleChunk ? `${titleChunk} - Заголовок сайта` : 'Заголовок сайта';
  }
})
</script>

Теперь, если вы установите заголовок Моя страница с помощью useHead на другой странице вашего сайта, заголовок будет отображаться как 'Моя страница - Заголовок сайта' на вкладке браузера. Вы также можете передать null, чтобы по умолчанию отображался «Заголовок сайта».

Template Params

You can use templateParams to provide additional placeholders in your titleTemplate besides the default %s. This allows for more dynamic title generation.

<script setup lang="ts">
useHead({
  titleTemplate: (titleChunk) => {
    return titleChunk ? `${titleChunk} %separator %siteName` : '%siteName';
  },
  templateParams: {
    siteName: 'Site Title',
    separator: '-'
  }
})
</script>

Теги body

Вы можете использовать опцию tagPosition: 'bodyClose' для соответствующих тегов, чтобы добавить их в конец тега <body>.

Например:

<script setup lang="ts">
useHead({
  script: [
    {
      src: 'https://third-party-script.com',
      // допустимые варианты: 'head' | 'bodyClose' | 'bodyOpen'
      tagPosition: 'bodyClose'
    }
  ]
})
</script>

Примеры

Используя definePageMeta

В директории pages/ вы можете использовать definePageMeta вместе с useHead, чтобы установить мета-данные на основе текущего маршрута.

Например, сначала можно установить заголовок текущей страницы (он извлекается во время сборки с помощью макроса, поэтому не может быть установлен динамически):

pages/some-page.vue
<script setup lang="ts">
definePageMeta({
  title: 'Some Page'
})
</script>

А затем в файле лэйаута вы можете использовать мета-данные маршрута, которые вы установили ранее:

layouts/default.vue
<script setup lang="ts">
const route = useRoute()

useHead({
  meta: [{ property: 'og:title', content: `Название приложения - ${route.meta.title}` }]
})
</script>
Прочитайте и отредактируйте живой пример в Docs > Examples > Features > Meta Tags.
Узнать больше Docs > Guide > Directory Structure > Pages > #page Metadata.

Динамический title

В примере ниже titleTemplate задается либо как строка с заполнителем %s, либо как функция, что позволяет более гибко устанавливать заголовок страницы динамически для каждого маршрута вашего приложения Nuxt:

app.vue
<script setup lang="ts">
useHead({
  // в виде строки,
  // где `%s` заменяется на заголовок
  titleTemplate: '%s - Site Title',
})
</script>
app.vue
<script setup lang="ts">
useHead({
  // или в виде функции
  titleTemplate: (productCategory) => {
    return productCategory
      ? `${productCategory} - Site Title`
      : 'Site Title'
  }
})
</script>

nuxt.config также используется в качестве альтернативного способа установки заголовка страницы. Однако nuxt.config не позволяет сделать заголовок страницы динамическим. Поэтому рекомендуется использовать titleTemplate в файле app.vue для добавления динамического заголовка, который затем применяется ко всем маршрутам вашего приложения Nuxt.

Внешний CSS

В примере ниже показано, как можно включить Google Fonts, используя свойство link композабла useHead или компонент <Link>:

<script setup lang="ts">
useHead({
  link: [
    {
      rel: 'preconnect',
      href: 'https://fonts.googleapis.com'
    },
    {
      rel: 'stylesheet',
      href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap',
      crossorigin: ''
    }
  ]
})
</script>