🐷

next-sitemapで特定箇所を指定してサイトマップを作成する

2022/07/17に公開

こちら備忘録です。

現在の現場にてサイトマップを作成して欲しいとのオーダーがあり、その時の備忘録です。
(一部改修しながらやっていますので、もっと良い方法がある!ということがありましたらぜひコメントください。)

要望されたのは

・サイトマップの作成
・あまり更新はしない。
・機能面部分はサイトマップに載せたくない。

とのことでした。

使用環境は

・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

https://github.com/iamvishnusankar/next-sitemap

・公式
https://vercel.com/support/articles/how-do-i-generate-a-sitemap-for-my-nextjs-app-on-vercel

自分はこちらのキカガクさんの記事を参考に導入しました。
こちらの方がシンプルでわかりやすいかなと思います。
・キカガク様の導入例
https://fwywd.com/tech/next-sitemap

導入についてはほぼ同じ記事があるのでここでは割愛して行きます。

自分は自動でpublicに設定する方法を使用しました。使用する前にignoreの設定もお忘れなく。

.gitignore
#next-sitemap
/public/robots.txt
/public/sitemap*.xml

サイトマップの指定方法

ここからが本題ですが、特定の箇所だけ指定する方法は結論から言うと2パターンあります。

・exclude
・additionalPaths

オプション内容はこちらに記載されています。

この二つを使用します。

exclude

指定したディレクトリ、ファイルを除外することができます。
ワイルドカードの記法が適応可能なので、例えば

-content
 --content1
 --content2

こんな感じのディレクトリがありcontent以下はいらない場合

/content*

のような書き方をすれば除外が適応されます。

sitemap.config.js
/** @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

この二つを利用して以下のように書き換えました。

sitemap.config.js
/** @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