つかったこのサイトについて

apex と www、どちらを本体にするか決める前にデプロイしない

独自ドメインを取って Vercel に繋いだときの話です。

example.dev(apex)と www.example.dev、どちらも登録できます。 登録すると、片方が本体で、もう片方が本体へ転送される形になります。

この向きを決めないまま進めました。

症状:何も壊れて見えない

サイトは開きます。apex で開いても www で開いても、ちゃんと表示されます。エラーはどこにも出ません。

ずれていたのは、次の3つの一致でした。

何を指していたか
実際に配信されるホスト www
<link rel="canonical"> apex
sitemap.xml の <loc> apex

検索エンジンに「本体はこちらです」と伝えているURLが、実際にはもう一方へ転送されるURLでした。

人間の目には何も起きていません。転送は正常に動いているからです。

なぜ気づきにくいか

転送が「逆」でも、転送そのものは機能します。ブラウザは黙って追従します。

気づくのは、次のどれかをわざわざ見に行ったときだけです。

  • curl -I https://example.dev を叩いて、301 が返ってくるのを見る
  • ページのソースで <link rel="canonical"> を確認する
  • sitemap.xml を開いて、並んでいるURLのホスト名を見る

ブラウザで普通に開いている限り、一生気づきません。

確認するコマンド

デプロイ直後にこれだけ叩けば分かります。

curl -sI https://example.dev     | grep -i "^HTTP\|^location"
curl -sI https://www.example.dev | grep -i "^HTTP\|^location"

片方が 200、もう片方が 301(または 308)で、Location が 200 の側を指していれば正常です。

そのうえで、200 が返ってきたホストと、次の2つが一致しているかを見ます。

curl -s https://example.dev | grep -i "rel=\"canonical\""
curl -s https://example.dev/sitemap.xml | head -5

直し方

1. どちらを本体にするか決める

技術的な優劣はほとんどありません。決めていないことが問題であって、どちらでもよい。

私は apex(example.dev)を本体にしました。短いからです。

2. Vercel のドメイン設定で転送の向きを直す

Vercel の Domains 画面で、本体にしたいほうを主にして、もう一方に「本体へリダイレクト」を設定します。

3. コード側を本体に揃える

Next.js なら、canonical と sitemap が同じ定数を見るようにしておくと、ずれようがなくなります。

// lib/site.ts
export const site = {
  url: process.env.NEXT_PUBLIC_SITE_URL ?? "https://example.dev",
};
// app/sitemap.ts
import { site } from "@/lib/site";

export default function sitemap(): MetadataRoute.Sitemap {
  return [{ url: site.url, lastModified: new Date() }];
}

環境変数に既定値を持たせておくのが要点です。未設定でも正しいURLになります。設定できる場所が増えるほど、ずれる場所も増えます。

ついでに:Cloudflare 側で詰まるところ

ドメインを Cloudflare で取って Vercel に向ける場合、プロキシ(オレンジ色の雲マーク)を「DNSのみ」(灰色)にします。

オレンジのままだと、Vercel 側の証明書の発行に失敗することがあります。 ここが一番詰まりやすい箇所でした。

もうひとつ、.dev は HTTPS が必須の TLD です。証明書が出るまでサイトは一切開きません。設定直後にエラー画面が出ても、少し待ってからもう一度確認してください。手を加えて直そうとすると、たいてい悪化します。

チェックリスト

独自ドメインを繋いだ直後に、これだけ見ておけば足ります。

  • apex と www のどちらを本体にするか決めた
  • curl -sI で、片方が 200、もう片方が 301/308 で本体を指している
  • canonical が本体のホストになっている
  • sitemap.xml の <loc> が本体のホストになっている
  • Cloudflare のプロキシが「DNSのみ」になっている
  • 証明書が発行され、HTTPS で開ける

この記事は、実際に設定して詰まった記録をもとに書いています。 ドメイン名は伏せてあります。

VercelCloudflareドメインSEONext.js