爆速で Next.js x microCMS で作成したブログに動的な sitemap.xml を追加する
爆速で Next.js x microCMS で作成したブログに動的な sitemap.xml を追加する方法をまとめます
前回
前回「爆速で Next.js x microCMS で作成したブログに robots.txt とsitemap.xml を追加する」で静的なsitemap.xmlを作成する方法をまとめました。作成したsitemap.xmlがこちらでした。
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://zubora-code.net/sitemap-0.xml</loc></sitemap>
</sitemapindex>
<?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>https://zubora-code.net/ja</loc><lastmod>2023-09-03T04:51:50.821Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/en</loc><lastmod>2023-09-03T04:51:50.821Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/ja/aboutme</loc><lastmod>2023-09-03T04:51:50.821Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/en/aboutme</loc><lastmod>2023-09-03T04:51:50.821Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/ja/privacy_policy</loc><lastmod>2023-09-03T04:51:50.821Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/en/privacy_policy</loc><lastmod>2023-09-03T04:51:50.821Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
</urlset>
今回は動的に生成されるURL (本ブログの場合は /articles と /tags 以下のURL) に対応する方法をまとめます。基本的には以下に書いてある通りですが、microCMSのAPIを叩く部分を追加します。なお、本記事ではApp Routerに対応した書き方についてまとめますが、Pages Routerについても以下に記載されており、ほとんど変わりません。
https://www.npmjs.com/package/next-sitemap
動的なURLをsitemapに追加する方法
大まかなアイデアとしては、動的なURLをmicroCMSのAPIを叩いて取得し、 server-sitemap.xml
というURLでアクセス可能な状態として、sitemap.xmlから参照します。
microCMSのAPIを叩いて動的なURLを取得して返却する
まずappディレクトリの下に server-sitemap.xml
ディレクトリを作成し、その中に route.ts
を作成します。
.
├── app
│ └── server-sitemap.xml
│ └── route.ts
※ちなみに上記は Homebrew で tree というコマンドをインストールして表示しています。
$ brew install tree
$ tree src
続いて、microCMSのAPIを叩いて記事一覧とタグ一覧を取得し、next-sitemapの getServerSideSitemap
という関数に渡します。
import { getServerSideSitemap, ISitemapField } from 'next-sitemap'
import { Article, getList, getTagList, Tag } from '@/libs/microcms'
import { formatYYYYMMDD } from '@/libs/dateutil'
import { NUM_OF_ALL_PAGES_LIMIST, NUM_OF_PAGES_LIMIT } from '@/constants'
// cache for 24 hours
export const revalidate = 86400
export async function GET(request: Request) {
const articlesData = await getList({
limit: NUM_OF_ALL_PAGES_LIMIST,
fields: 'id,updatedAt',
})
const articles = articlesData.contents
const tagsData = await getTagList({
limit: NUM_OF_PAGES_LIMIT,
})
const tags = tagsData.contents
const fields: ISitemapField[] = []
articles.forEach((article: Article) => {
;['ja', 'en'].forEach((locale) => {
fields.push({
loc: `${process.env.NEXT_PUBLIC_BASE_URL}/${locale}/articles/${article.id}`,
lastmod: formatYYYYMMDD(article.updatedAt),
priority: 1, // Priority of this URL compared to other URLs within the site.
changefreq: 'weekly', // Page update frequency.
})
})
})
tags.forEach((tag: Tag) => {
;['ja', 'en'].forEach((locale) => {
fields.push({
loc: `${process.env.NEXT_PUBLIC_BASE_URL}/${locale}/tags/${tag.id}`,
lastmod: formatYYYYMMDD(tag.updatedAt),
priority: 1, // Priority of this URL compared to other URLs within the site.
changefreq: 'weekly', // Page update frequency.
})
})
})
return getServerSideSitemap(fields)
}
注意点として、App Router の場合は default で fetch のレスポンスが cache されるようになっていますが、 revalidate = 86400
を指定しておくことで、24時間に一度値が更新される状態にしておきます。Next.js の Cache の詳しい挙動に関しては以下をご確認ください。
next-sitemap.cnfig.js
に以下を追加しておきます。
module.exports = {
siteUrl: 'https://zubora-code.net',
generateRobotsTxt: true,
exclude: ['/server-sitemap.xml'], // Add this line
robotsTxtOptions: {
additionalSitemaps: ['https://zubora-code.net/server-sitemap.xml'], // Add this line
},
sitemapSize: 7000,
}
また、本ブログの場合は middleware.ts にも以下を追加して、middlewareの処理実行対象外にしておきます。
export const config = {
matcher: [
'/((?!robots.txt|sitemap.*.xml|server-sitemap.xml|api|_next/static|_next/image|favicon.ico|.*.png|.*.jpg).*)',
],
}
生成されるsitemapの確認
buildとstartを実行すると、以下のsitemapがそれぞれ生成されます。
$ yarn build
$ yarn start
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://zubora-code.net/sitemap-0.xml</loc></sitemap>
<sitemap><loc>https://zubora-code.net/server-sitemap.xml</loc></sitemap>
</sitemapindex>
<?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>https://zubora-code.net/ja</loc><lastmod>2023-09-09T23:56:05.065Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/en</loc><lastmod>2023-09-09T23:56:05.065Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/ja/privacy_policy</loc><lastmod>2023-09-09T23:56:05.065Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/en/privacy_policy</loc><lastmod>2023-09-09T23:56:05.065Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/ja/aboutme</loc><lastmod>2023-09-09T23:56:05.065Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://zubora-code.net/en/aboutme</loc><lastmod>2023-09-09T23:56:05.065Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
</urlset>
ブラウザで http://localhost:3000/server-sitemap.xml
にアクセスすると、以下のように表示されました。(かなり長いため中略しています。)
<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>https://zubora-code.net/ja/articles/screen-recording-with-sound</loc>
<lastmod>2023-09-07</lastmod>
<changefreq>weekly</changefreq>
<priority>1</priority>
</url>
<url>
...
<loc>https://zubora-code.net/ja/tags/sitemap</loc>
<lastmod>2023-09-10</lastmod>
<changefreq>weekly</changefreq>
<priority>1</priority>
</url>
<url>
...
</urlset>
これを本番環境にデプロイすると、無事以下のように表示されました。
https://zubora-code.net/sitemap.xml
https://zubora-code.net/server-sitemap.xml
汚くなってしまいましたが、今回の変更は以下のPR3つで対応しました。
https://github.com/tkugimot/nextjs-microcms-blog-handson/pull/23?w=1
https://github.com/tkugimot/nextjs-microcms-blog-handson/pull/24/files?w=1
https://github.com/tkugimot/nextjs-microcms-blog-handson/pull/25/files?w=1
あとは放っておいてもGoogleが拾いに来てくれるはずですが、一応 Google Search Console からサイトマップを再登録しておきます。
以上です! これで多少はSEOが改善されることを祈ります!