next-sitemapで特定箇所を指定してサイトマップを作成する
こちら備忘録です。
現在の現場にてサイトマップを作成して欲しいとのオーダーがあり、その時の備忘録です。
(一部改修しながらやっていますので、もっと良い方法がある!ということがありましたらぜひコメントください。)
要望されたのは
・サイトマップの作成
・あまり更新はしない。
・機能面部分はサイトマップに載せたくない。
とのことでした。
使用環境は
・Macbook Pro M1
・OS Monterey
・Next.js 12.1.0
・TypeScript 4.6.2
・vercel
.node 14.19.1
となっております。
next-sitemapをインストールする
2つ候補がありましたが、そのうちのnext-sitemapの方が簡単だし、自分がいない時でも作業しやすいかなと思いこちらを導入しました。
公式でもsitemapの導入方法は記載されています。
next-sitemap
・公式
自分はこちらのキカガクさんの記事を参考に導入しました。
こちらの方がシンプルでわかりやすいかなと思います。
・キカガク様の導入例
導入についてはほぼ同じ記事があるのでここでは割愛して行きます。
自分は自動でpublicに設定する方法を使用しました。使用する前にignoreの設定もお忘れなく。
#next-sitemap
/public/robots.txt
/public/sitemap*.xml
サイトマップの指定方法
ここからが本題ですが、特定の箇所だけ指定する方法は結論から言うと2パターンあります。
・exclude
・additionalPaths
この二つを使用します。
exclude
指定したディレクトリ、ファイルを除外することができます。
ワイルドカードの記法が適応可能なので、例えば
-content
--content1
--content2
こんな感じのディレクトリがありcontent以下はいらない場合
/content*
のような書き方をすれば除外が適応されます。
/** @type {import('next-sitemap').IConfig} */
module.exports = {
siteUrl: process.env.NEXT_PUBLIC_SITE_URL,
exclude: ['/*'],
generateRobotsTxt: true,
};
こんな感じに書くと全部サイトマップには表示されません。
additionalPaths
こちらは、逆のパターンというか指定した部分の表示を行えるオプションです。
説明を翻訳してみたところこんな感じに書かれています。
additionalPaths この関数は、大きなページのリストがあるけれども、それらをすべてレンダリングしたくない場合、fallback: trueを使用すると便利です。この関数を実行した結果は、一般的なパスのリストに追加され、sitemapSizeで処理されます。動的なパスを追加するのは自由ですが、additionalSitemapとは異なり、1つのファイルに対して多くのパスがある場合に、パスのリストを別のファイルに分割する必要はありません。
もし関数が既に存在するパスを返した場合、そのパスは単に更新されるだけで、重複は起こりません。
とのことです。
公式の書き方は以下になります。
/** @type {import('next-sitemap').IConfig} */
const config = {
additionalPaths: async (config) => {
const result = []
// required value only
result.push({ loc: '/additional-page-1' })
// all possible values
result.push({
loc: '/additional-page-2',
changefreq: 'yearly',
priority: 0.7,
lastmod: new Date().toISOString(),
// acts only on '/additional-page-2'
alternateRefs: [
{
href: 'https://es.example.com',
hreflang: 'es',
},
{
href: 'https://fr.example.com',
hreflang: 'fr',
},
],
})
// using transformation from the current configuration
result.push(await config.transform(config, '/additional-page-3'))
return result
},
}
export default config
この二つを利用して以下のように書き換えました。
/** @type {import('next-sitemap').IConfig} */
module.exports = {
siteUrl: process.env.NEXT_PUBLIC_SITE_URL,
exclude: ['/*'],
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
additionalPaths: async () => {
const result = [];
result.push(
{
loc: '/aaa',
},
{
loc: '/bbb',
},
{
loc: '/ccc',
},
);
return result;
},
generateRobotsTxt: true,
};
型で怒られてしまって、改善できなかったため
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
で逃げちゃいました💦(書き方良い方法ありましたら、ぜひ教えて欲しいです。)
すると、サイトマップ(初期設定だとsitemap-0.xml)にはこのような形で表記できます。
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url><loc>http://localhost:3001/aaa</loc></url>
<url><loc>http://localhost:3001/bbb</loc></url>
<url><loc>http://localhost:3001/ccc</loc></url>
</urlset>
もちろん公式のように
priority
等も設定できますが、こちらを見ると
priorityと changefreq の値を無視します。
lastmod 値が一貫して正確であることを(ページの最終更新との比較などにより)検証できる場合に、この値を使用します。
とのことなので除外しています。
lastmodについてはこちらに
省略可能とのことで除外しました。
The date of last modification of the page. This date should be in W3C Datetime format. This format allows you to omit the time portion, if desired, and use YYYY-MM-DD.
まだ改良できると思いますが、こちらで一旦要件を満たしたので今回はここまでを記録しておきます。
Discussion