Skip to content

Next.js - 元数据

Next.js - 管理页面元数据(Metadata)

Section titled “Next.js - 管理页面元数据(Metadata)”

修改 HTML 页面的 <head> 部分对于 SEO(搜索引擎优化)、社交媒体分享(Open Graph 标签)以及向浏览器提供上下文信息(如设置页面标题)至关重要。

Next.js 提供了不同的方法来管理元数据,具体取决于你使用的是 App Router 还是 Pages Router。

App Router 引入了一个强大的 Metadata API。你可以通过从 layout.js 或 page.js 文件中导出静态 metadata 对象或动态 generateMetadata 函数来定义元数据。

静态示例(app/about/page.js):

import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'About Us | My Awesome Site',
description: 'Learn more about our company and team.',
openGraph: {
title: 'About Us | My Awesome Site',
description: 'Learn more about our company and team.',
// images: ['/path/to/image.jpg'],
},
};
export default function AboutPage() {
return (
<div>
<h1>About Us</h1>
<p>This page uses the static Metadata API.</p>
</div>
);
}

动态示例(app/posts/[slug]/page.js): 抓取数据以生成元数据。

import { Metadata, ResolvingMetadata } from 'next';
// 用于抓取文章数据的函数(替换为你实际的数据抓取逻辑)
async function getPostData(slug) {
// const res = await fetch(`.../api/posts/${slug}`)
// const post = await res.json()
// return post
return { title: `Post: ${slug}`, excerpt: `Details about post ${slug}` };
}
type Props = {
params: { slug: string };
searchParams: { [key: string]: string | string[] | undefined };
};
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
// 读取路由参数
const slug = params.slug;
// 抓取数据
const post = await getPostData(slug);
// 可选:访问并扩展(而非替换)父级元数据
// const previousImages = (await parent).openGraph?.images || [];
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
// images: ['/some-specific-post-image.jpg', ...previousImages],
},
};
}
export default async function PostPage({ params }: Props) {
const post = await getPostData(params.slug);
return (
<div>
<h1>{post.title}</h1>
<p>This page uses the dynamic generateMetadata function.</p>
</div>
);
}

Metadata API 会自动处理合并父级布局中的元数据并对标签进行去重,这使得它更加健壮且易于管理。

在 Pages Router 中,你使用从 next/head 导入的内置 Head 组件。你放在 <Head> 中的任何标签都会被附加到最终 HTML 的 <head> 部分。

让我们更新示例页面(pages/index.js 和 pages/posts/first-post.js),使用 <Head> 包含标题和 meta 描述。

更新 pages/index.js:

import Link from 'next/link';
import Head from 'next/head'; // 导入 Head
function HomePage() {
return (
<>
{/* 添加 Head 组件 */}
<Head>
<title>Welcome to My Next.js Site!</title>
<meta name="description" content="The homepage of my awesome Next.js application" />
{/* 你可以在此处添加其他标签,例如 Open Graph meta 标签 */}
<meta property="og:title" content="Welcome to My Next.js Site!" />
</Head>
<div>
<h1>Welcome to Next.js!</h1>
<Link href="/posts/first-post">
<a>Go to First Post</a>
</Link>
</div>
</>
);
}
export default HomePage;

更新 pages/posts/first-post.js:

import Link from 'next/link';
import Head from 'next/head'; // 导入 Head
import Layout from '../../components/layout'; // 假设 Layout 组件存在
export default function FirstPost() {
return (
<Layout>
{/* 添加 Head 组件 */}
<Head>
<title>My First Post | Next.js Blog</title>
<meta name="description" content="Reading the very first post on this blog." />
</Head>
<h1>My First Post</h1>
<p>This is the content of the first post.</p>
<h2>
<Link href="/">
<a>Back to home</a>
</Link>
</h2>
</Layout>
);
}

如果渲染树中的多个组件使用具有相同标签的 <Head>(例如,多个 <title> 标签),Next.js 会自动进行去重,通常会保留最后定义的那个。为了确保像 <meta name="description"> 这样的标签的唯一性,可以添加一个唯一的 key 属性:<meta name="description" key="desc" content="..." />。

如果服务器尚未运行,请启动它:

npm run dev
# 示例输出:
# ready - started server on 0.0.0.0:3000, url: http://localhost:3000
  1. 在浏览器中打开 http://localhost:3000。检查浏览器标签页标题——它应该显示 ‘Welcome to My Next.js Site!’。查看页面源代码(右键 -> 查看页面源代码或使用浏览器开发者工具)并检查 <head> 部分。你应该能找到在 pages/index.js 中定义的 <title> 和 <meta name="description"> 标签。

  2. 点击链接导航到“First Post”(/posts/first-post)。观察浏览器标签页标题变为 ‘My First Post | Next.js Blog’。再次检查页面源代码;<head> 部分现在应该包含在 pages/posts/first-post.js 中定义的元数据。

正确管理元数据对于搜索引擎如何索引你的网站以及链接在社交媒体平台分享时的显示效果至关重要。