Next 元数据(metadata)
基于配置的元数据
静态元数据还是动态元数据都只在服务端组件中支持,尽可能使用静态元数据。
静态元数据
在 layout.js 或 page.js 中,导出 Metadata 对象
1 |
|
动态元数据
使用动态元数据要借助 generateMetadata
函数返回一个 Metadata 对象。
1 |
|
该函数接收两个参数,props 和 parent,props 包含当前路由参数的对象,该对象有 params 和 searchParams 两个属性
params 是动态路由参数的对象,当访问非动态路由,params 为 {}
路由 | url | params |
---|---|---|
app/shop/[slug]/page.js | /shop/1 | { slug: ‘1’ } |
app/shop/[tag]/[item]/page.js | /shop/1/2 | { tag: ‘1’, item: ‘2’ } |
app/shop/[…slug]/page.js | /shop/1/2 | { slug: [‘1’, ‘2’] } |
searchParams 是 URLSearchParams 对象,包含了 URL 中的查询参数
url | searchParams |
---|---|
/shop?a=1 | { a: ‘1’ } |
/shop?a=1&b=2 | { a: ‘1’, b: ‘2’ } |
/shop?a=1&a=2 | { a: [‘1’, ‘2’] } |
parent 是一个包含父路由段 metadata 对象的 promise 对象,需要使用 (await parent).openGraph 获取。
字段覆盖
Next 会对各层的元数据进行浅合并,离当前页面越近的元数据会覆盖离当前页面越远的元数据。
字段继承
当前页的元数据会继承自己没定义的上层的元数据。
1 |
|
1 |
|
如上,page.js 中未定义 openGraph 而 他的上层 layout 定义了,所以 page 会继承 layout 的 openGraph 字段。
JSON-LD
JSON-LD 可以向搜索引擎描述网站上的内容。 在 Next 中使用 JSON-LD 可以在 layout 或者 page 中使用 script 标签。
1 |
|
基于文件的元数据
基于文件的元数据优先级更高,会覆盖基于配置的元数据。
图标
Next 的图标就是在 /app 目录下的 favicon
、icon
、apple-icon
图片文件。
favicon
必须要在顶层目录(如 /app 或 /src/app)下,icon
和 apple-icon
可以放在更深层的目录。
File convention | Supported file types | Valid locations | Link ref |
---|---|---|---|
favicon | .ico | app/ | |
icon | .ico、.jpg、.jpeg、.png、.svg | app/**/* | |
apple-icon | .jpg、.jpeg、.png | app/**/* |
不同尺寸图标
还可以在一个目录下放多个不同尺寸 icon ,可以根据不同尺寸显示不同 icon。
使用代码生成
文件名还是 icon 或者 apple-icon 后缀为 js、ts、tsx,通过 next/og的 ImageResponse 即可生成一个图标。
1 |
|
robot
robot 用于告诉搜索引擎可以爬取网站中的哪些 URL,Next 中有两种方式设置 robot。
- 静态文件
在 app/ 下创建 robot.txt 即可1
2
3
4User-Agent: *
Allow: /
Disallow: /private/
Sitemap: https://acme.com/sitemap.xml - 代码生成
使用 robot.js / robot.ts1
2
3
4
5
6
7
8
9
10export default function robots() {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: '/private/',
},
sitemap: 'https://acme.com/sitemap.xml',
}
}
站点地图 sitemap.xml
站点地图是一个 XML 文件,用于告诉搜索引擎网站的结构,Next 中可以使用静态文件 sitemap.xml 或者 sitemap.js / sitemap.ts 生成站点地图。
- 静态文件
app/sitemap.xml:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://acme.com</loc>
<lastmod>2023-04-06T15:02:24.021Z</lastmod>
<changefreq>yearly</changefreq>
<priority>1</priority>
</url>
<url>
<loc>https://acme.com/about</loc>
<lastmod>2023-04-06T15:02:24.021Z</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://acme.com/blog</loc>
<lastmod>2023-04-06T15:02:24.021Z</lastmod>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
</urlset> - 代码生成
使用 sitemap.js / sitemap.ts1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22export default function sitemap() {
return [
{
url: 'https://acme.com',
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 1,
},
{
url: 'https://acme.com/about',
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: 'https://acme.com/blog',
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.5,
},
]
}
metadata 属性
- title
值可以是字符串,也可以是对象,使用对象时,default 为子路由没定义 title 的默认值,template 为子路由添加一个前缀或者后缀,并且使用 template 的话,必须同时 有 default。1
2
3
4
5
6
7
8export const metadata = {
title: {
template: '%s | Acme', // %s 会被替换为子路由的 title
default: 'Acme',
absolute: 'About' // 设置标题,会忽略上层路由段设置的 title.template
},
} - description
设置页面的描述 - metadataBase
设置 metadata 字段中地址的前缀输出结果1
2
3
4
5
6
7
8
9
10
11
12
13
14// layout.js | page.js
export const metadata = {
metadataBase: new URL('https://acme.com'),
alternates: {
canonical: '/',
languages: {
'en-US': '/en-US',
'de-DE': '/de-DE',
},
},
openGraph: {
images: '/og-image.png',
},
}使用 metadataBase 后,metadata 的地址还可以使用相对地址,Next 会进行自动合并,还会智能的处理多余的斜杠,当然如果 metadata 设置了绝对地址,metadataBase 会被忽略1
2
3
4<link rel="canonical" href="https://acme.com" />
<link rel="alternate" hreflang="en-US" href="https://acme.com/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://acme.com/de-DE" />
<meta property="og:image" content="https://acme.com/og-image.png" /> - openGraph输出
1
2
3
4
5
6
7
8
9export const metadata = {
openGraph: {
title: 'Next.js',
description: 'The React Framework for the Web',
type: 'article',
publishedTime: '2023-01-01T00:00:00.000Z',
authors: ['Seb', 'Josh'],
},
}1
2
3
4
5
6<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2023-01-01T00:00:00.000Z" />
<meta property="article:author" content="Seb" />
<meta property="article:author" content="Josh" /> - robots输出的 HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// layout.js | page.js
export const metadata = {
robots: {
index: false,
follow: true,
nocache: true,
googleBot: {
index: true,
follow: false,
noimageindex: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
}…1
2
3
4
5<meta name="robots" content="noindex, follow, nocache" />
<meta
name="googlebot"
content="index, nofollow, noimageindex, max-video-preview:-1, max-image-preview:large, max-snippet:-1"
/>