Next.js元数据与SEO #
一、元数据基础 #
1.1 元数据概念 #
元数据是用于描述网页的信息,包括标题、描述、关键词等,对SEO和社交分享至关重要。
1.2 静态元数据 #
tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: '我的网站',
description: '这是一个使用 Next.js 构建的网站',
}
export default function Page() {
return <div>页面内容</div>
}
1.3 动态元数据 #
tsx
import type { Metadata } from 'next'
interface PageProps {
params: Promise<{ slug: string }>
}
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
const { slug } = await params
const post = await getPost(slug)
return {
title: post.title,
description: post.excerpt,
}
}
export default function Page({ params }: PageProps) {
return <div>页面内容</div>
}
二、元数据字段 #
2.1 基本字段 #
tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: '页面标题',
description: '页面描述',
keywords: ['Next.js', 'React', 'JavaScript'],
authors: [{ name: '作者名' }],
creator: '创建者',
publisher: '发布者',
robots: {
index: true,
follow: true,
},
}
2.2 标题模板 #
tsx
export const metadata: Metadata = {
title: {
default: '我的网站',
template: '%s | 我的网站',
},
}
子页面使用:
tsx
export const metadata: Metadata = {
title: '关于我们',
}
生成结果:关于我们 | 我的网站
2.3 图标配置 #
tsx
export const metadata: Metadata = {
icons: {
icon: '/favicon.ico',
shortcut: '/favicon-16x16.png',
apple: '/apple-touch-icon.png',
},
}
2.4 manifest #
tsx
export const metadata: Metadata = {
manifest: '/manifest.json',
}
三、Open Graph #
3.1 基本配置 #
tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
openGraph: {
title: '页面标题',
description: '页面描述',
url: 'https://example.com/page',
siteName: '网站名称',
images: [
{
url: 'https://example.com/og-image.png',
width: 1200,
height: 630,
alt: '图片描述',
},
],
locale: 'zh_CN',
type: 'website',
},
}
3.2 文章类型 #
tsx
export const metadata: Metadata = {
openGraph: {
title: '文章标题',
description: '文章描述',
type: 'article',
publishedTime: '2024-01-01',
authors: ['作者名'],
tags: ['Next.js', 'React'],
images: [
{
url: 'https://example.com/article-image.png',
width: 1200,
height: 630,
},
],
},
}
3.3 动态Open Graph #
tsx
interface PageProps {
params: Promise<{ slug: string }>
}
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
const { slug } = await params
const post = await getPost(slug)
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
type: 'article',
publishedTime: post.publishedAt,
authors: [post.author.name],
images: [
{
url: post.coverImage,
width: 1200,
height: 630,
alt: post.title,
},
],
},
}
}
四、Twitter卡片 #
4.1 基本配置 #
tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
twitter: {
card: 'summary_large_image',
title: '页面标题',
description: '页面描述',
creator: '@twitter_handle',
images: ['https://example.com/twitter-image.png'],
},
}
4.2 卡片类型 #
| 类型 | 说明 |
|---|---|
| summary | 小图片摘要卡片 |
| summary_large_image | 大图片摘要卡片 |
| player | 视频/音频播放器 |
| app | 应用卡片 |
4.3 完整示例 #
tsx
export const metadata: Metadata = {
twitter: {
card: 'summary_large_image',
site: '@site_handle',
creator: '@creator_handle',
title: '文章标题',
description: '文章描述',
images: [
{
url: 'https://example.com/twitter-image.png',
width: 1200,
height: 630,
alt: '图片描述',
},
],
},
}
五、其他SEO配置 #
5.1 规范链接 #
tsx
export const metadata: Metadata = {
alternates: {
canonical: 'https://example.com/page',
languages: {
'zh-CN': 'https://example.com/zh/page',
'en-US': 'https://example.com/en/page',
},
},
}
5.2 站点地图 #
tsx
import { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: 'https://example.com',
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
{
url: 'https://example.com/about',
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: 'https://example.com/blog',
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.9,
},
]
}
5.3 robots.txt #
tsx
import { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: ['/api/', '/admin/'],
},
sitemap: 'https://example.com/sitemap.xml',
}
}
5.4 结构化数据 #
tsx
export default function ProductPage({ product }) {
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
description: product.description,
image: product.image,
offers: {
'@type': 'Offer',
price: product.price,
priceCurrency: 'CNY',
availability: 'https://schema.org/InStock',
},
}
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<div>产品内容</div>
</>
)
}
六、完整示例 #
6.1 博客文章页面 #
tsx
import type { Metadata } from 'next'
import { MetadataRoute } from 'next'
interface PageProps {
params: Promise<{ slug: string }>
}
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
const { slug } = await params
const post = await getPost(slug)
return {
title: post.title,
description: post.excerpt,
keywords: post.tags,
authors: [{ name: post.author.name }],
openGraph: {
title: post.title,
description: post.excerpt,
type: 'article',
publishedTime: post.publishedAt,
modifiedTime: post.updatedAt,
authors: [post.author.name],
tags: post.tags,
images: [
{
url: post.coverImage,
width: 1200,
height: 630,
alt: post.title,
},
],
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.excerpt,
images: [post.coverImage],
},
alternates: {
canonical: `https://example.com/blog/${post.slug}`,
},
}
}
export default async function BlogPost({ params }: PageProps) {
const { slug } = await params
const post = await getPost(slug)
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: post.title,
description: post.excerpt,
image: post.coverImage,
datePublished: post.publishedAt,
dateModified: post.updatedAt,
author: {
'@type': 'Person',
name: post.author.name,
},
}
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<article>
<h1>{post.title}</h1>
<div>{post.content}</div>
</article>
</>
)
}
6.2 产品页面 #
tsx
import type { Metadata } from 'next'
interface PageProps {
params: Promise<{ id: string }>
}
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
const { id } = await params
const product = await getProduct(id)
return {
title: product.name,
description: product.description,
openGraph: {
title: product.name,
description: product.description,
type: 'product',
images: [
{
url: product.image,
width: 800,
height: 800,
alt: product.name,
},
],
},
twitter: {
card: 'summary_large_image',
title: product.name,
description: product.description,
images: [product.image],
},
}
}
export default async function ProductPage({ params }: PageProps) {
const { id } = await params
const product = await getProduct(id)
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
description: product.description,
image: product.image,
brand: {
'@type': 'Brand',
name: product.brand,
},
offers: {
'@type': 'Offer',
price: product.price,
priceCurrency: 'CNY',
availability: product.inStock
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
},
}
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<div>产品内容</div>
</>
)
}
七、最佳实践 #
7.1 元数据继承 #
布局中的元数据会被子页面继承:
tsx
export const metadata: Metadata = {
title: {
default: '我的网站',
template: '%s | 我的网站',
},
description: '网站描述',
openGraph: {
siteName: '我的网站',
},
}
7.2 合并策略 #
tsx
export const metadata: Metadata = {
title: '页面标题',
openGraph: {
title: 'OG标题',
},
}
7.3 图片优化 #
tsx
export const metadata: Metadata = {
openGraph: {
images: [
{
url: '/og-image.png',
width: 1200,
height: 630,
alt: '描述',
},
],
},
}
八、总结 #
元数据与SEO要点:
| 要点 | 说明 |
|---|---|
| 静态元数据 | export const metadata |
| 动态元数据 | generateMetadata函数 |
| Open Graph | 社交分享优化 |
| Twitter卡片 | Twitter分享优化 |
| 结构化数据 | 搜索引擎理解内容 |
| 站点地图 | 搜索引擎索引 |
下一步,让我们学习导航与链接!
最后更新:2026-03-28