Next.js 13でのmetaタグの管理にはMetadata APIを使用しますが、その際canonical
の表示に少しハマったのでメモします。
Metadata APIとは
Next.js 12以前まではHeadコンポーネントを利用して直接書いていましたが、Next.js 13以降では推奨されていません。
index.tsx
import Head from 'next/head'
function IndexPage() {
return (
<div>
<Head>
<title>My page title</title>
<meta property="og:title" content="My page title" key="title" />
<link rel="canonical" href="https://example.com/" />
</Head>
</div>
)
}
export default IndexPage
以下のコードは公式サイトのドキュメントに記載されているものです。
静的ページの場合はmetadata関数内にメタデータを記述します。動的ページはgenerateMetadata関数を利用して記事ページなどのIDをparamsとして受け取り、そこからフェッチしたデータからメタデータを取得します。
layout.tsx
import { Metadata } from 'next'
// 静的メタデータの場合
export const metadata: Metadata = {
title: '...',
}
layout.tsx
import { Metadata } from 'next'
type Props = {
params: { id: string }
}
// 動的メタデータの場合
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { id } = params
const post = await fetch(`endpoint/${id}`).then((res) => res.json())
return {
title: post.title,
}
}
canonicalはalternateもセットに考える
ただし、canonicalはそのままcanonical
と記述するとエラーとなるため、以下のようにalternatesプロパティを使う必要があります。
layout.tsx
import { Metadata } from 'next'
// 静的メタデータの場合
export const metadata: Metadata = {
title: "Your title",
description: "Your meta description",
- canonical: "https://example.com",
+ alternates: {
+ canonical: "https://example.com",
+ },
}
layout.tsx
import { Metadata } from 'next'
type Props = {
params: { id: string, slug: string }
}
// 動的メタデータの場合
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { id, slug } = params;
const post = await fetch(`endpoint/${id}`).then((res) => res.json());
return {
title: post.title,
description: post.description,
- canonical: `https://example.com/${slug}`,
+ alternates: {
+ canonical: `https://example.com/${slug}`,
+ },
};
}
私自身alternate
タグを意識して使ったことがなかったのですが、PC用ページとは別にスマホ用ページが存在する場合、URL正規化するためにGoogleに伝えるのがalternate
タグだそうです。
Metadata APIの場合、alternate
とcanonical
をセットとして覚える必要がありそうですね。
参考資料
この記事はこちらを参考に作成しました。