SEO とメタデータ

強力なhead設定、コンポーザブル、コンポーネントで、NuxtアプリのSEOを改善しましょう。

Nuxtのヘッドタグ管理はUnheadによって提供されます。これは、アプリのheadとSEOメタタグを管理するための、合理的なデフォルト設定、いくつかの強力なコンポーザブル、そして多数の設定オプションを提供します。

Nuxt設定

nuxt.config.ts 内に app.head プロパティを提供することで、アプリ全体のheadを静的にカスタマイズできます。

この方法では、リアクティブなデータを提供できません。app.vueuseHead() を使用することをお勧めします。

サイトのタイトルデフォルト、言語、ファビコンなど、変更されないタグをここで設定することをお勧めします。

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' },
      ],
    },
  },
})

Types に記載されているキーをすべて提供することもできます。

デフォルトタグ

Nuxtは、サイトがすぐに機能するように、いくつかのタグをデフォルトで提供しています。

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

ほとんどのサイトではこれらのデフォルトをオーバーライドする必要はありませんが、キー付きショートカットを使用して更新できます。

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

useHead コンポーザブル関数はリアクティブな入力をサポートしており、headタグをプログラムで管理できます。

app/app.vue
<script setup lang="ts">
useHead({
  title: 'My App',
  meta: [
    { name: 'description', content: 'My amazing site.' },
  ],
  bodyAttrs: {
    class: 'test',
  },
  script: [{ innerHTML: 'console.log(\'Hello world\')' }],
})
</script>

useHeaduseHeadSafe のコンポーザブルをぜひご覧ください。

useSeoMeta

useSeoMeta コンポーザブルを使用すると、サイトのSEOメタタグを完全に型安全なオブジェクトとして定義できます。

これにより、property の代わりに name を使用するなどのタイプミスや一般的な間違いを防ぐことができます。

app/app.vue
<script setup lang="ts">
useSeoMeta({
  title: 'My Amazing Site',
  ogTitle: 'My Amazing Site',
  description: 'This is my amazing site, let me tell you all about it.',
  ogDescription: 'This is my amazing site, let me tell you all about it.',
  ogImage: 'https://example.com/image.png',
  twitterCard: 'summary_large_image',
})
</script>
詳しくは Docs > 4 X > API > Composables > Use Seo Meta を参照してください。

コンポーネント

すべての場合において useHead の使用が推奨されますが、テンプレートでコンポーネントを使用してヘッドタグを定義することを好む場合もあるかもしれません。

Nuxt はこの目的のために以下のコンポーネントを提供しています: <Title>, <Base>, <NoScript>, <Style>, <Meta>, <Link>, <Body>, <Html>, <Head>。これらのコンポーネントは大文字で始まることに注意してください。これにより、無効なネイティブHTMLタグを使用しないようにしています。

<Head><Body> はネストされたメタタグを受け入れることができます (美的理由による) が、これは最終的な HTML でネストされたメタタグが *どこ* にレンダリングされるかには影響しません。

app/app.vue
<script setup lang="ts">
const title = ref('Hello World')
</script>

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

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

タグがより直感的に重複排除されるため、コンポーネントを <Head> または <Html> コンポーネントのいずれかでラップすることをお勧めします。

タイプ

以下は、useHeadapp.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より詳細な型については、こちらを参照してください。

機能

リアクティビティ

すべてのプロパティで、算出値、ゲッター、またはリアクティブオブジェクトを提供することで、リアクティビティがサポートされます。

<script setup lang="ts">
const description = ref('My amazing site.')

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

タイトルテンプレート

titleTemplate オプションを使用すると、サイトのタイトルをカスタマイズするための動的なテンプレートを提供できます。たとえば、サイトの名前をすべてのページのタイトルに追加できます。

titleTemplate は文字列にすることができ、その場合 %s はタイトルに置き換えられます。または関数にすることもできます。

関数を使用したい場合(完全に制御したい場合)、nuxt.config で設定することはできません。代わりに、app.vue ファイル内で設定することをお勧めします。そうすれば、サイトのすべてのページに適用されます。

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

これで、サイトの別のページで useHead を使用してタイトルを My Page に設定すると、ブラウザのタブには「My Page - Site Title」と表示されます。また、null を渡すと「Site Title」がデフォルトになります。

テンプレートパラメータ

templateParams を使用すると、titleTemplate にデフォルトの %s 以外の追加のプレースホルダーを提供できます。これにより、より動的なタイトル生成が可能になります。

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

ボディタグ

適用可能なタグに tagPosition: 'bodyClose' オプションを使用すると、それらを <body> タグの末尾に追加できます。

例:

<script setup lang="ts">
useHead({
  script: [
    {
      src: 'https://third-party-script.com',
      // valid options are: 'head' | 'bodyClose' | 'bodyOpen'
      tagPosition: 'bodyClose',
    },
  ],
})
</script>

definePageMeta を使用して

app/pages/ ディレクトリ 内で、definePageMetauseHead を組み合わせて、現在のルートに基づいてメタデータを設定できます。

たとえば、まず現在のページタイトルを設定できます (これはビルド時にマクロによって抽出されるため、動的に設定することはできません)。

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: `App Name - ${route.meta.title}` }],
})
</script>
Docs > 4 X > Examples > Features > Meta Tags でライブの例を読んで編集してください。
詳細は Docs > 4 X > Guide > Directory Structure > App > Pages > #page Metadata を参照してください。

動的なタイトル

以下の例では、titleTemplate%s プレースホルダーを含む文字列として、または function として設定され、Nuxtアプリの各ルートのページタイトルを動的に設定する際に、より柔軟な対応が可能になります。

app/app.vue
<script setup lang="ts">
useHead({
  // as a string,
  // where `%s` is replaced with the title
  titleTemplate: '%s - Site Title',
})
</script>
app/app.vue
<script setup lang="ts">
useHead({
  // or as a function
  titleTemplate: (productCategory) => {
    return productCategory
      ? `${productCategory} - Site Title`
      : 'Site Title'
  },
})
</script>

nuxt.config もページタイトルを設定する別の方法として使用されます。しかし、nuxt.config ではページタイトルを動的にすることはできません。したがって、Nuxtアプリのすべてのルートに適用される動的なタイトルを追加するには、app.vue ファイルで titleTemplate を使用することをお勧めします。

外部CSS

以下の例は、useHead コンポーザブルの link プロパティを使用するか、<Link> コンポーネントを使用していかに Google Fonts を有効にするかを示しています。

<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>