自作サイトでハマった「末尾スラッシュ」の話 — canonical との噛み合わせ

このブログを自分で作っていて、地味だけれど気づきにくいバグにハマりました。 原因は、URL の末尾に付く「/(スラッシュ)」ひとつです。 たったそれだけで、検索エンジンから見たページが二重になりかけていました。

同じ落とし穴は、多くの自作サイトに潜んでいます。 専門用語はかみくだくので、コードが苦手でも読み進められます。

末尾スラッシュって何?

まず、次の 2 つの URL を見てください。

https://example.com/blog/hello
https://example.com/blog/hello/

最後に / が付いているかどうか、それだけの違いです。 人間の目には、同じページに見えます。 実際、ブラウザで開けば、どちらも同じ内容が表示されます。

ところが、検索エンジンにとっては「別々の URL」に見えることがあります。 ここが、今回のつまずきの入り口でした。

末尾スラッシュの有無で同じページが2つのURLに見え、canonicalと統一で1つに集約する図

canonical タグって何?

こうした「同じ内容が複数の URL で見えてしまう」問題に備える印が、canonical(カノニカル)タグです。 ページの <head> に、こう書きます。

<link rel="canonical" href="https://example.com/blog/hello/" />

意味はシンプルです。 「このページの正式な URL は、これですよ」と検索エンジンに伝えるためのものです。 似た URL が複数あっても、canonical が指す 1 つに評価をまとめてくれます。

何が「噛み合わない」と、まずいのか

問題は、この canonical とサイトの他の部分が食い違うときに起きます。

たとえば、こういう状態です。

  • canonical は末尾スラッシュあり/blog/hello/)を指している
  • でも、サイト内のリンクやサイトマップは末尾スラッシュなし/blog/hello)で書かれている

すると検索エンジンは、こう迷います。 「リンクは /blog/hello、でも本人は /blog/hello/ が正式だと言っている。どっちを登録すればいい?」

この食い違いが続くと、インデックス(検索結果への登録)が割れたり、遅れたりします。 私の場合は、とくに Bing でうまく登録されない状態が起きていました。

なぜ気づきにくいのか

いちばんやっかいなのは、見た目では気づけないことです。

ブラウザで両方の URL を開くと、どちらも普通に表示されます。 サーバーが片方へ自動でリダイレクトしてくれることも多く、人間には「同じページ」にしか見えません。 だから、目視のチェックでは、まず見逃します。

検索エンジンだけが、URL の形の違いに厳密なのです。 人には同じ、機械には別。 このズレが、落とし穴になります。

どう直すか — URL の形を 1 つに統一する

直し方の芯は、ひとつだけです。 サイト全体で、URL の形を 1 つに統一すること。

具体的には、次の 3 つを同じ形にそろえます。

  1. canonical タグ
  2. サイトマップ(sitemap)
  3. サイト内のすべての内部リンク

そのうえで、サーバー側で「片方の形にリダイレクト」しておけば万全です。

このブログは Astro というフレームワークで作っているので、設定ファイルに一行足して「末尾スラッシュあり」に統一しました。

// astro.config.mjs
export default defineConfig({
  site: 'https://example.com',
  trailingSlash: 'always', // 末尾スラッシュを必須の形にする
});

配信先の Cloudflare Pages 側も、スラッシュ無しでアクセスされたら、自動でスラッシュ有りへリダイレクトしてくれます。 これで、入り口・案内・正式 URL のすべてが「末尾スラッシュあり」で一致しました。

確認のしかた

直したら、必ず「本当にそろっているか」を確かめます。 私は、ビルドした成果物を検索して、末尾スラッシュ無しのリンクが残っていないかを見ました。

# canonical の形を確認する
grep -r 'rel="canonical"' dist/

# 内部リンクの末尾スラッシュがそろっているか
grep -rE 'href="/blog[^"/]*"' dist/

2 つ目のコマンドで何もヒットしなければ、末尾スラッシュ無しの内部リンクはゼロ、ということです。 canonical・サイトマップ・内部リンクが同じ形になっていれば、合格です。

「あり」と「なし」、どっちに統一する?

ここでよくある疑問が、「末尾スラッシュは、あり・なしのどちらに統一すべき?」です。

結論を言うと、どちらでも構いません。大事なのは、サイト全体で片方に統一することです。

強いて言えば、静的サイトはページをフォルダ単位で書き出すことが多く、その場合は「あり」(/blog/hello/)が自然になじみます。 このブログも「あり」で統一しました。 逆に「なし」で通すなら、canonical もサイトマップもリンクも、すべて「なし」でそろえます。 どちらを選んでも、混ぜないことだけが唯一のルールです。

学んだこと

この一件で、いちばん腹落ちしたのは、これです。 派手なコンテンツより先に、URL の正規化という「土台」を固めておくべきだった。

末尾スラッシュは、動かなくなるバグではありません。 ページはちゃんと表示されるので、放っておいても気づきません。 けれど、土台がずれていると、あとからコンテンツを積み上げるほど、検索での損が静かに広がっていきます。

小さな / ひとつ。 けれど、検索から見つけてもらうことを大事にするなら、最初に詰めておく価値のある一文字でした。