Cloud Storage のオブジェクトURLと Website Hosting URL で相対パスの挙動が全然違う話

Next.js の静的サイトを next export して、
Cloud Storage に置いて公開しようとしたときの話です。

「リンク先が https://storage.googleapis.com/page/2.html になってバケット名が消える」
という謎現象にハマりました。

原因は、Cloud Storage の 2 種類の URL を混同していたことでした。


Cloud Storage には URL が 2 種類ある

1. オブジェクト URL(Cloud Console が見せてくるやつ)

例:

https://storage.googleapis.com/xxxx/index.html

これは 「単なるオブジェクトへの API URL」 で、
静的サイトホスティングとしての機能は何も持っていません。

特徴:

  • index.html 自動表示なし
  • 相対リンク /page/2.htmlhttps://storage.googleapis.com/page/2.html に解決される(バケット無視)
  • Cloud Storage の「ウェブサイト構成」で設定した index / 404 が効かない

2. Website Hosting URL(本当に使うべき側)

例:

https://xxxxxx.storage.googleapis.com/

こちらは 静的サイトホスティングとしての振る舞いをします。

特徴:

  • / にアクセスすると index.html が自動で返される
  • 相対リンク /page/2.html
    https://xxxxxx.storage.googleapis.com/page/2.html に解決
  • Cloud Storage の「ウェブサイト構成」で設定した index / 404 が有効

実際に起きたトラブル

最初、ブラウザで開いていた URL はこれでした:

https://storage.googleapis.com/xxxxxx/index.html

Cloud Console の「公開 URL」からそのまま開いた形です。

この状態で、ページ内のリンクを /page/2.html にしていると…

https://storage.googleapis.com/page/2.html

に飛びます。

つまり:

  • バケット名 xxxxxx が完全に消える
  • 当然 404
  • 「相対パスのはずなのに、どこ行った?」状態

になりました。


なぜこうなるのか?

https://storage.googleapis.com/...あくまでオブジェクト API の入り口であって、
「サイトルート」という概念がありません。

一方で、

https://<bucket-name>.storage.googleapis.com/

は「そのバケットを静的サイトとして扱う」ための入口なので、
相対パスも「バケットをルート」として解決されます。

そのため、

  • 誤: https://storage.googleapis.com/xxxxxx/index.html
  • 正: https://xxxxxx.storage.googleapis.com/index.html

という違いだけで、相対パスの挙動がまったく変わります。


Website Hosting を有効にする

Cloud Storage 側で「ウェブサイト構成」をしておくと、

  • メインページ: index.html
  • 404 ページ: 404.html(任意)

などを設定できます。

ただし、この設定が効くのは https://<bucket>.storage.googleapis.com/ の方だけです。
https://storage.googleapis.com/bucket/index.html の方には一切効きません。


正しい URL の決め方

  1. バケット名を確認する(例: xxxxxx
  2. URL を次の形式でアクセスする:
https://xxxxxx.storage.googleapis.com/
  1. ここから /page/2.html/posts/slug.html など相対リンクを貼る

これだけで、Next.js の next export で生成された静的サイトが素直に動きます。


まとめ

Cloud Storage の URL は見た目が似ていて紛らわしいですが、役割はまったく違います。

種類 用途 相対パス ホスティング設定
オブジェクト URL https://storage.googleapis.com/bucket/index.html API / 個別ファイル参照 ❌ 壊れる ❌ 無効
Website Hosting URL https://bucket.storage.googleapis.com/index.html 静的サイト公開 ✔ 正しく解決 ✔ 有効

Next.js や静的 HTML を GCS に置いて公開したい場合は、
必ず https://<bucket>.storage.googleapis.com/ を「サイトの URL」として使う
というのが教訓でした。

「Cloud Storage の公開 URL をそのままブログ URL にしてるけど、相対パスが変なところに飛ぶ…」という人は、
一度 URL の形式を見直してみると解決するかもしれません。