詮釋資料
Next.js 有一個詮釋資料 API,可用於定義應用程式詮釋資料(例如 HTML head
元素內的 meta
和 link
標籤),以改善 SEO 和網頁分享能力。
您可以透過兩種方式將詮釋資料新增至您的應用程式
- 基於設定的詮釋資料:在
layout.js
或page.js
檔案中匯出靜態metadata
物件或動態generateMetadata
函式。 - 基於檔案的詮釋資料:將靜態或動態生成的特殊檔案新增至路由區段。
透過這兩種選項,Next.js 將自動為您的頁面產生相關的 <head>
元素。您也可以使用 ImageResponse
建構函式建立動態 OG 圖片。
靜態詮釋資料
要定義靜態詮釋資料,請從 layout.js
或靜態 page.js
檔案匯出 Metadata
物件。
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: '...',
description: '...',
}
export default function Page() {}
關於所有可用的選項,請參閱API 參考。
動態詮釋資料
您可以使用 generateMetadata
函式來 fetch
需要動態值的詮釋資料。
import type { Metadata, ResolvingMetadata } from 'next'
type Props = {
params: Promise<{ id: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
// read route params
const id = (await params).id
// fetch data
const product = await fetch(`https://.../${id}`).then((res) => res.json())
// optionally access and extend (rather than replace) parent metadata
const previousImages = (await parent).openGraph?.images || []
return {
title: product.title,
openGraph: {
images: ['/some-specific-page-image.jpg', ...previousImages],
},
}
}
export default function Page({ params, searchParams }: Props) {}
關於所有可用的參數,請參閱 API 參考。
注意事項:
基於檔案的詮釋資料
以下特殊檔案可用於詮釋資料
- favicon.ico、apple-icon.jpg 和 icon.jpg
- opengraph-image.jpg 和 twitter-image.jpg
- robots.txt
- sitemap.xml
您可以將這些檔案用於靜態詮釋資料,也可以使用程式碼以程式設計方式產生這些檔案。
關於實作和範例,請參閱 詮釋資料檔案 API 參考和 動態圖片產生。
行為
基於檔案的詮釋資料具有較高的優先順序,並且會覆寫任何基於設定的詮釋資料。
預設欄位
即使路由沒有定義詮釋資料,也始終會新增兩個預設的 meta
標籤
- meta charset 標籤設定網站的字元編碼。
- meta viewport 標籤設定網站的視窗寬度和縮放比例,以便適應不同的裝置。
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
貼心小提醒:您可以覆寫預設的
viewport
meta 標籤。
順序
中繼資料會依順序進行評估,從根區段開始,向下到最接近最終 page.js
區段的區段。例如:
app/layout.tsx
(根佈局)app/blog/layout.tsx
(巢狀部落格佈局)app/blog/[slug]/page.tsx
(部落格頁面)
合併
遵循評估順序,從同一路徑的多個區段匯出的中繼資料物件會進行**淺層**合併,以形成路徑的最終中繼資料輸出。重複的鍵會根據其順序被**取代**。
這表示具有巢狀欄位的中繼資料,例如在較早區段中定義的 openGraph
和 robots
,會被最後定義它們的區段**覆寫**。
覆寫欄位
export const metadata = {
title: 'Acme',
openGraph: {
title: 'Acme',
description: 'Acme is a...',
},
}
export const metadata = {
title: 'Blog',
openGraph: {
title: 'Blog',
},
}
// Output:
// <title>Blog</title>
// <meta property="og:title" content="Blog" />
在上述範例中:
app/layout.js
中的title
會被app/blog/page.js
中的title
**取代**。app/layout.js
中的所有openGraph
欄位都會在app/blog/page.js
中被**取代**,因為app/blog/page.js
設定了openGraph
中繼資料。請注意缺少openGraph.description
。
如果您想要在區段之間共享一些巢狀欄位,同時覆寫其他欄位,您可以將它們提取到一個單獨的變數中。
export const openGraphImage = { images: ['http://...'] }
import { openGraphImage } from './shared-metadata'
export const metadata = {
openGraph: {
...openGraphImage,
title: 'Home',
},
}
import { openGraphImage } from '../shared-metadata'
export const metadata = {
openGraph: {
...openGraphImage,
title: 'About',
},
}
在上述範例中,OG 圖片在 app/layout.js
和 app/about/page.js
之間共享,而標題則不同。
欄位繼承
export const metadata = {
title: 'Acme',
openGraph: {
title: 'Acme',
description: 'Acme is a...',
},
}
export const metadata = {
title: 'About',
}
// Output:
// <title>About</title>
// <meta property="og:title" content="Acme" />
// <meta property="og:description" content="Acme is a..." />
注意事項
app/layout.js
中的title
會被app/about/page.js
中的title
**取代**。- 由於
app/about/page.js
沒有設定openGraph
中繼資料,所有app/layout.js
中的openGraph
欄位都會被app/about/page.js
**繼承**。
動態圖片產生
ImageResponse
建構函式允許您使用 JSX 和 CSS 產生動態圖片。這對於建立社群媒體圖片(例如 Open Graph 圖片、Twitter 卡片等)非常有用。
要使用它,您可以從 next/og
導入 ImageResponse
。
import { ImageResponse } from 'next/og'
export async function GET() {
return new ImageResponse(
(
<div
style={{
fontSize: 128,
background: 'white',
width: '100%',
height: '100%',
display: 'flex',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
}}
>
Hello world!
</div>
),
{
width: 1200,
height: 600,
}
)
}
ImageResponse
與其他 Next.js API 良好整合,包括路由處理程式和基於檔案的中繼資料。例如,您可以在 opengraph-image.tsx
檔案中使用 ImageResponse
,在建置時或請求時動態產生 Open Graph 圖片。
ImageResponse
支援常見的 CSS 屬性,包括 flexbox 和絕對定位、自訂字體、文字換行、置中和巢狀圖片。查看支援的 CSS 屬性完整清單。
注意事項:
- 範例可在Vercel OG Playground中找到。
ImageResponse
使用@vercel/og、Satori 和 Resvg 將 HTML 和 CSS 轉換為 PNG。- 僅支援 Edge Runtime。預設的 Node.js 執行環境將無法運作。
- 僅支援 flexbox 和部分 CSS 屬性。進階排版(例如
display: grid
)將無法運作。- 最大 bundle 大小為
500KB
。bundle 大小包含您的 JSX、CSS、字體、圖片和任何其他資源。如果超過限制,請考慮減少任何資源的大小或在執行階段擷取。- 僅支援
ttf
、otf
和woff
字體格式。為了最大限度地提高字體解析速度,建議使用ttf
或otf
,而不是woff
。
JSON-LD
JSON-LD 是一種結構化資料格式,搜尋引擎可以使用它來理解您的內容。例如,您可以使用它來描述人物、事件、組織、電影、書籍、食譜和許多其他類型的實體。
我們目前建議您在 layout.js
或 page.js
元件中將 JSON-LD 結構化資料渲染為 <script>
標籤。例如:
export default async function Page({ params }) {
const product = await getProduct(params.id)
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
image: product.image,
description: product.description,
}
return (
<section>
{/* Add JSON-LD to your page */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
{/* ... */}
</section>
)
}
您可以使用 Google 的 富媒體搜尋結果測試 或通用的 Schema 標記驗證器 來驗證和測試您的結構化資料。
您可以使用像 schema-dts
這樣的社群套件,使用 TypeScript 撰寫您的 JSON-LD。
import { Product, WithContext } from 'schema-dts'
const jsonLd: WithContext<Product> = {
'@context': 'https://schema.org',
'@type': 'Product',
name: 'Next.js Sticker',
image: 'https://nextjs.dev.org.tw/imgs/sticker.png',
description: 'Dynamic at the speed of static.',
}
下一步 (Next Steps)
這有幫助嗎?