Zubora Code

爆速で Next.js x microCMS で作成したブログに動的な sitemap.xml を追加する

爆速で Next.js x microCMS で作成したブログに動的な sitemap.xml を追加する方法をまとめます

Published: 10 September, 2023
Revised: 10 September, 2023

前回

前回「爆速で 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 の詳しい挙動に関しては以下をご確認ください。

https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#segment-cache-configuration


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が改善されることを祈ります!

Toshimitsu Kugimoto

Software Engineer

仕事では決済やメディアのWebやスマホアプリのBE開発、WebのFE開発をやっています。 JavaとTypeScriptをよく使います。プライベートではFlutterでのアプリ開発にも挑戦中です。