🍆

next-sitemapでサイトマップを生成する際に気をつけたいこと【outDirは罠】

2023/03/02に公開

next-sitemapはNext.jsで制作したWebアプリケーションのサイトマップを簡単に生成してくれる便利なパッケージです。

outDir オプションを使用して出力ディレクトリを変更する際に気をつけるべきだと思いましたので情報共有します。

どんな問題が起きるかが分かるサンプル

https://github.com/masa5714/next-sitemap-outdir-sample

next-sitemap.config.jsの記述

/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: process.env.SITE_URL || 'https://hoge.jp/',
  generateRobotsTxt: true,
  outDir: './public/fugafuga', // fugafugaディレクトリに出力するように指定
}

こちらの内容でサイトマップ生成を行うと /public/fugafuga の中に

  • robots.txt
  • sitemap.xml
  • sitemap-0.xml
    を生成してくれます。

問題はここからです。

robots.txt と sitemap.xmlが outDirに適した記述になっていない

見出しの通り、 robots.txtとsitemap.xmlがoutDirで指定したディレクトリを向いてくれていません。生成された記述を見てみましょう。

robots.txt
# *
User-agent: *
Allow: /

# Host
Host: https://hoge.jp

# Sitemaps
Sitemap: https://hoge.jp/sitemap.xml <- ★ 問題はこの行です
sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://hoge.jp/sitemap-0.xml</loc></sitemap>  <- ★ 問題はこの行です
</sitemapindex>

ご覧の通り、 /public に生成された場合のパスを向いていることが分かります。

それぞれ問題の記述は

Sitemap: https://hoge.jp/fugafuga/sitemap.xml だったり、
<sitemap><loc>https://hoge.jp/fugafuga/sitemap-0.xml</loc></sitemap> となっているべきです。

修正をしなければせっかく生成したサイトマップにアクセスできず、全く意味がありません。

問題を無理やり解決する

sitemap-replace.js
const replaceSitemap = async (fileName) => {
  const fs = require('fs/promises')
  const appRoot = require('app-root-path')
  const subDirectory = 'fugafuga' // ここディレクトリを変更する
  const filePath = `${appRoot}/public/${subDirectory}/${fileName}`

  const original = await fs.readFile(filePath, 'utf8')
  const replacedData = original.replace(
    /https\:\/\/hoge\.jp\/sitemap/g,  // ここドメインを変更する
    `https://hoge.jp/${subDirectory}/sitemap`  // ここドメインを変更する
  )

  await fs.writeFile(filePath, replacedData, 'utf8')
}

;(async () => {
  await replaceSitemap('robots.txt')
  await replaceSitemap('sitemap.xml')
})()

こんなJSファイルを用意しました。
package.json の postbuildnext-sitemap && node sitemap-replace.js として、サイトマップ生成後に置換されるようにしておけば解決できます。

置換後は下記のようになります。

robots.txt
# *
User-agent: *
Allow: /

# Host
Host: https://hoge.jp

# Sitemaps
Sitemap: https://hoge.jp/fugafuga/sitemap.xml
sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://hoge.jp/fugafuga/sitemap-0.xml</loc></sitemap>
</sitemapindex>

issues立ててあります

果たしてこれは仕様なのかどうかは分かりませんが、せっかく生成したサイトマップが参照されなければ全く意味がありません。

この問題(?)は Github にて issues を立ててあります。(DeepL純度100%の英語)

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

天才エンジニアの皆さん、ぜひプルリクエストを送って根本的な解決をしてください!(他力本願)

そもそもなぜ出力ディレクトリを変更する必要があるのか?

サイトマップの保存場所を知られたくないからです。
自分自身がスクレイピング大好きなのですが、スクレイピングする際には初手サイトマップを探します。サイトマップを見つければ大勝利です。サイト側からリンクリストを提供してくれてる訳ですから、そのリストを元にスクレイピングすればほぼ全ページ巡回できてしまいます。

サイトマップの保存場所はGoogleにだけ知ってもらえば十分です。
Googleに知ってもらえば Yahoo!Japan でも、Bingでもちゃんと検索ヒットします。

スクレイパーたちにサイトマップの場所を知らせる必要はありません。

デフォルトのままだと /sitemap.xml で巡回し放題です。

そして下記の方法でpropsデータを取得できるので、低コストでスクレイピングされてしまいます。スクレイピングのハードルを少しでも上げるならディレクトリ変更をオススメします。
僕はランダムな文字列にしています。
https://zenn.dev/masa5714/articles/4927bbded40419

Discussion