SEO 和 Meta

使用强大的 head 配置、可组合项和组件来提升 Nuxt 应用的 SEO。

Nuxt head 标签管理由 Unhead 提供支持。它提供合理的默认值、多个强大的可组合项以及众多配置选项,用于管理应用的 head 和 SEO 元标签。

¥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 配置

¥Nuxt Config

nuxt.config.ts 中提供 app.head 属性,可以静态自定义整个应用的 head 部分。

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

此方法不允许你提供响应式数据。我们建议在 app.vue 中使用 useHead()

最好在此处设置不会更改的标签,例如网站默认标题、语言和网站图标。

¥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

Nuxt 默认提供某些标签,以确保你的网站开箱即用。

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

  • viewportwidth=device-width, initial-scale=1
  • charsetutf-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

useHead 可组合函数支持响应式输入,允许你以编程式方式管理 head 标签。

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

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 可组合项。

¥We recommend to take a look at the useHead and useHeadSafe composables.

useSeoMeta

useSeoMeta 可组合项允许你将网站的 SEO 元标记定义为具有完全类型安全的对象。

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

这有助于你避免拼写错误和常见错误,例如将 property 写成 name

¥This helps you avoid typos and common mistakes, such as using name instead of property.

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>
Read more in Docs > API > Composables > Use Seo Meta.

组件

¥Components

虽然建议在所有情况下都使用 useHead,但你可能更喜欢使用组件在模板中定义 head 标签。

¥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>。请注意这些组件的首字母大写,以确保我们不会使用无效的原生 HTML 标签。

¥Nuxt provides the following components for this purpose: <Title>, <Base>, <NoScript>, <Style>, <Meta>, <Link>, <Body>, <Html> and <Head>. Note the capitalization of these components ensuring we don't use invalid native HTML tags.

<Head><Body> 可以接受嵌套的元标记(出于美观原因),但这不会影响嵌套元标记在最终 HTML 中的渲染位置。

¥<Head> and <Body> can accept nested meta tags (for aesthetic reasons) but this does not affect where the nested meta tags are rendered in the final HTML.

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> 组件中,因为这样可以更直观地删除标签。

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

类型

¥Types

以下是用于 useHeadapp.head 和组件的非反应式类型。

¥Below are the non-reactive types used for useHead, app.head and components.

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

¥See @unhead/vue for more detailed types.

功能

¥Features

响应式

¥Reactivity

所有属性都支持响应式,可以通过提供计算值、getter 或响应式对象来实现。

¥Reactivity is supported on all properties, by providing a computed value, a getter, or a reactive object.

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

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

标题模板

¥Title Template

你可以使用 titleTemplate 选项提供动态模板来自定义网站标题。例如,你可以将网站名称添加到每个页面的标题中。

¥You can use the titleTemplate option to provide a dynamic template for customizing the title of your site. For example, you could add the name of your site to the title of every page.

titleTemplate 可以是字符串(其中 %s 用标题替换),也可以是一个函数。

¥The titleTemplate can either be a string, where %s is replaced with the title, or a function.

如果你想使用函数(以实现完全控制),则无法在 nuxt.config 中设置。建议在 app.vue 文件中设置它,它将应用于你网站上的所有页面:

¥If you want to use a function (for full control), then this cannot be set in your nuxt.config. It is recommended instead to set it within your app.vue file where it will apply to all pages on your site:

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

现在,如果你在网站的另一个页面上使用 useHead 将标题设置为 My Page,则标题将显示为“我的页面” - 浏览器标签页中的“网站标题”。你也可以将 null 传递给 '站点标题' 的默认值。

¥Now, if you set the title to My Page with useHead on another page of your site, the title would appear as 'My Page - Site Title' in the browser tab. You could also pass null to default to 'Site Title'.

模板参数

¥Template Params

除了默认的 %s 之外,你还可以使用 templateParamstitleTemplate 中提供额外的占位符。这允许更动态的标题生成。

¥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 标签

¥Body Tags

你可以在适用的标签上使用 tagPosition: 'bodyClose' 选项,将它们附加到 <body> 标签的末尾。

¥You can use the tagPosition: 'bodyClose' option on applicable tags to append them to the end of the <body> tag.

例如:

¥For example:

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

示例

¥Examples

使用 definePageMeta

¥With definePageMeta

在你的 pages/ 目录 中,你可以将 definePageMetauseHead 结合使用,根据当前路由设置元数据。

¥Within your pages/ directory, you can use definePageMeta along with useHead to set metadata based on the current route.

例如,你可以先设置当前页面标题(该标题在构建时通过宏提取,因此无法动态设置):

¥For example, you can first set the current page title (this is extracted at build time via a macro, so it can't be set dynamically):

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

然后,在你的布局文件中,你可以使用之前设置的路由元数据:

¥And then in your layout file, you might use the route's metadata you have previously set:

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

useHead({
  meta: [{ property: 'og:title', content: `App Name - ${route.meta.title}` }]
})
</script>
Read and edit a live example in Docs > Examples > Features > Meta Tags.
Read more in Docs > Guide > Directory Structure > Pages > #page Metadata.

动态标题

¥Dynamic Title

在下面的示例中,titleTemplate 可以设置为带有 %s 占位符的字符串,也可以设置为 function,这样可以更灵活地为 Nuxt 应用的每个路由动态设置页面标题:

¥In the example below, titleTemplate is set either as a string with the %s placeholder or as a function, which allows greater flexibility in setting the page title dynamically for each route of your 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.vue
<script setup lang="ts">
useHead({
  // or as a function
  titleTemplate: (productCategory) => {
    return productCategory
      ? `${productCategory} - Site Title`
      : 'Site Title'
  }
})
</script>

nuxt.config 也可用作设置页面标题的替代方法。但是,nuxt.config 不允许页面标题是动态的。因此,建议在 app.vue 文件中使用 titleTemplate 添加动态标题,然后将其应用于 Nuxt 应用的所有路由。

¥nuxt.config is also used as an alternative way of setting the page title. However, nuxt.config does not allow the page title to be dynamic. Therefore, it is recommended to use titleTemplate in the app.vue file to add a dynamic title, which is then applied to all routes of your Nuxt app.

外部 CSS

¥External CSS

以下示例展示了如何使用 useHead 可组合项的 link 属性或使用 <Link> 组件启用 Google 字体:

¥The example below shows how you might enable Google Fonts using either the link property of the useHead composable or using the <Link> component:

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