next-sitemapでサイトマップを生成する際に気をつけたいこと【outDirは罠】
next-sitemapはNext.jsで制作したWebアプリケーションのサイトマップを簡単に生成してくれる便利なパッケージです。
outDir
オプションを使用して出力ディレクトリを変更する際に気をつけるべきだと思いましたので情報共有します。
どんな問題が起きるかが分かるサンプル
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で指定したディレクトリを向いてくれていません。生成された記述を見てみましょう。
# *
User-agent: *
Allow: /
# Host
Host: https://hoge.jp
# Sitemaps
Sitemap: https://hoge.jp/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>
となっているべきです。
修正をしなければせっかく生成したサイトマップにアクセスできず、全く意味がありません。
問題を無理やり解決する
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 の postbuild
に next-sitemap && node sitemap-replace.js
として、サイトマップ生成後に置換されるようにしておけば解決できます。
置換後は下記のようになります。
# *
User-agent: *
Allow: /
# Host
Host: https://hoge.jp
# Sitemaps
Sitemap: https://hoge.jp/fugafuga/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%の英語)
天才エンジニアの皆さん、ぜひプルリクエストを送って根本的な解決をしてください!(他力本願)
そもそもなぜ出力ディレクトリを変更する必要があるのか?
サイトマップの保存場所を知られたくないからです。
自分自身がスクレイピング大好きなのですが、スクレイピングする際には初手サイトマップを探します。サイトマップを見つければ大勝利です。サイト側からリンクリストを提供してくれてる訳ですから、そのリストを元にスクレイピングすればほぼ全ページ巡回できてしまいます。
サイトマップの保存場所はGoogleにだけ知ってもらえば十分です。
Googleに知ってもらえば Yahoo!Japan でも、Bingでもちゃんと検索ヒットします。
スクレイパーたちにサイトマップの場所を知らせる必要はありません。
デフォルトのままだと /sitemap.xml
で巡回し放題です。
そして下記の方法でpropsデータを取得できるので、低コストでスクレイピングされてしまいます。スクレイピングのハードルを少しでも上げるならディレクトリ変更をオススメします。
僕はランダムな文字列にしています。
Discussion