Nuxt4 SEO 与页面元信息
SEO 决定搜索引擎能否理解你的页面,以及搜索结果里展示什么内容。
SSR 是 Nuxt 的天然优势,页面 HTML 里就有完整内容,搜索引擎可以直接抓取。
页面标题的重要性
浏览器标签页显示标题,搜索引擎结果展示标题和描述。不同页面应该有不同的标题和描述,比如首页是「我的网站」,关于页是「关于我们 - 我的网站」。
useHead 基础用法
在页面中用 useHead 设置元信息:
<!-- app/pages/about.vue -->
<script setup>
useHead({
title: '关于我们',
meta: [
{ name: 'description', content: '这里是关于我们的介绍' },
{ name: 'keywords', content: 'Nuxt, Vue, 教程' }
]
})
</script>
<template>
<div>关于页面内容</div>
</template>
刷新页面,浏览器标签页会显示「关于我们」。在网页源码中可以看到自动生成的 <title> 和 <meta> 标签。
useSeoMeta 简化写法
useSeoMeta 是专为 SEO 设计的简化版,字段名更直观:
<script setup>
useSeoMeta({
title: '关于我们',
description: '这里是关于我们的介绍',
keywords: 'Nuxt, Vue, 教程',
ogTitle: '关于我们', // 社交分享标题
ogDescription: '分享给朋友看的描述', // 社交分享描述
ogImage: '/images/logo.png' // 社交分享封面图
})
</script>
og 开头的字段是 Open Graph 协议,控制页面被分享到微信、Twitter 等平台时显示的标题、描述和封面图。
动态标题
动态路由页面(如文章详情)标题应该跟随内容变化:
<!-- app/pages/posts/[id].vue -->
<script setup>
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.id}`)
// 数据到齐后设置标题
useSeoMeta({
title: () => `${post.value.title} - 我的网站`,
description: () => post.value.excerpt
})
</script>
useHead 和 useSeoMeta 的字段支持传入函数,函数返回值会自动更新,适合依赖响应式数据的场景。
全局默认设置
公共的默认值放在 app.vue 中设置,所有页面生效,页面级设置会覆盖同名项:
<!-- app/app.vue -->
<script setup>
useSeoMeta({
title: '我的网站',
description: '这是我的个人网站',
ogImage: '/images/logo.png'
})
</script>
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
页面里的 useSeoMeta 声明相同的字段(如 title)时,会覆盖全局值,没有声明的字段沿用全局值。这就是 SEO 配置的继承机制。
让页面内容被抓取
元信息之外,正文内容也要可被索引。SSR 模式下正文在 HTML 中,搜索引擎可以直接抓取。要注意两点:
- 不要依赖客户端 JS 渲染关键内容,搜索爬虫执行 JS 有限
- 图片要写
alt属性,方便图片搜索
站点级信息:nuxt-site-config
除了逐页设置标题,还应告诉搜索引擎「整个站点」的基本信息(规范网址、名称、描述)。最省事的做法是用 nuxt-site-config 模块,在 nuxt.config.ts 里写一次 site 块:
// nuxt.config.ts
export default defineNuxtConfig({
site: {
url: process.env.NUXT_SITE_URL || 'https://example.com',
name: '在线小工具',
description: '免费的在线小工具集合,纯前端处理,无需后端服务',
},
})
装好模块(npm i nuxt-site-config)并配置后,Nuxt 会自动把它注入到 <head> 的 og:site_name、canonical 等标签里,不用在每个页面重复写。本教程配套的在线工具站就是这么做的。
Sitemap 与 Robots
想让搜索引擎更快发现所有页面,需要 sitemap.xml(站点地图)和 robots.txt(爬取规则)。Nuxt 生态里有现成模块:
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
'@nuxtjs/sitemap',
'@nuxtjs/robots',
],
sitemap: {
// 自动收集路由生成 sitemap.xml,可设置更新频率和优先级
defaults: {
changefreq: 'weekly',
priority: 0.5,
},
},
robots: {
// 禁止爬取的内部接口目录
disallow: ['/api/'],
},
})
构建后站点根目录会生成 sitemap.xml 和 robots.txt。对于动态路由(如 /tools/[slug]),模块会按实际生成的路由自动收录,无需手动枚举。
结构化数据 JSON-LD
除了肉眼可见的标题描述,还可以给搜索引擎「机器可读」的结构化数据,帮助它在搜索结果里展示评分、价格等富媒体信息。常用做法是注入一段 JSON-LD 脚本,Nuxt 里用 useHead 实现:
<!-- app/pages/tools/[slug].vue -->
<script setup>
const tool = useTool() // 假设已拿到当前工具数据
useHead(() => ({
script: tool.value
? [{
type: 'application/ld+json',
innerHTML: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'SoftwareApplication',
name: tool.value.name,
description: tool.value.description,
applicationCategory: 'UtilitiesApplication',
operatingSystem: 'Any',
offers: { '@type': 'Offer', price: '0', priceCurrency: 'CNY' },
}),
}]
: [],
}))
</script>
上面这段来自本项目的工具详情页:每个工具都标注成「SoftwareApplication(免费软件)」,搜索引擎识别后可能展示更丰富的卡片。注意 innerHTML 里的内容要可信,不要拼接用户输入,避免被注入。
静态站点与预渲染
如果你的网站内容几乎不变(博客、官网),可以用静态生成模式。构建时把所有页面预渲染成 HTML,SEO 表现和 SSR 一样好,还能部署到 CDN 上。预渲染配置见配置与部署。
SEO 设置速查表
| 需求 | 写法 |
|---|---|
| 设置页面标题 | useSeoMeta({ title: '...' }) |
| 设置描述 | useSeoMeta({ description: '...' }) |
| 社交分享卡片 | useSeoMeta({ ogTitle, ogDescription, ogImage }) |
| 动态标题 | 字段传函数,如 title: () => post.value.title |
| 全局默认值 | 在 app.vue 中设置 |
| 覆盖全局值 | 页面中声明同名字段 |
| 站点级信息 | nuxt-site-config 的 site 块 |
| 站点地图 | @nuxtjs/sitemap 模块 |
| 爬取规则 | @nuxtjs/robots 模块的 robots 配置 |
| 结构化数据 | useHead 注入 JSON-LD 脚本 |
一句话总结:SSR 让内容天然可被抓取,useSeoMeta 负责标题、描述和社交分享信息,全局默认写在 app.vue,动态内容传函数。