注意事項
私はインフラエンジニアでありフロントエンドエンジニアではない為、Reactの理解が間違っている可能性があります。
間違っている箇所は、適宜指摘いただけたら嬉しいです。
GCSでReactのコンテンツを公開する為の基本設定
GCSでWebホスティングする為の設定
省略します。
公式ドキュメントを見て公開すれば、問題なく公開できます。
特殊ページの割り当て
Reactは、index.html の読み込みでブラウザにダウンロードした JavaScript がURLのパス文字列を解釈して、実体のファイルを取得します。
この為、404で返ってくるパスに対しても index.html を返すように設定する必要があります。
Reactでサブディレクトリを使う為の設定
GCSバケット上のトップディレクトリにindex.htmlがある場合で考えます。
例えば、https://example.com/hogehoge/ というサブディレクトリに対してのアクセスを行う場合、上記特殊ページの割り当てを行っておけば、表示自体は問題なくできます。
しかし、hogehoge へのアクセスは一度404となってからindex.htmlに着地する為、SEOの観点から問題が起きる可能性もあります。
動きとしては、以下となります。
- https://example.com/hogehote/ へブラウザからアクセス
- GCSバケット上に /hogehoge/index.html がない(hogehogeディレクトリ自体がない)為、404となる
- 404の為、GCSバケット上の /index.html がブラウザに返される
- ブラウザがReactの JavaScript を読み込み、パスを解釈して正常に動作する
Webコンテンツとしてはこれで問題なく動くのですが、2番の404が発生したタイミングで検索エンジンのインデックスから https://example.com/hogehoge/ が削除されてしまいます。
これを避けようとした場合、以下のどちらかを行う必要があります。
- /hogehoge/ ディレクトリ配下にも、Reactでビルドしたファイルを配置する
- /hogehoge/ ディレクトリ配下に来たアクセスを、/ に着地させる
本セクションでは、後者を Cloud Load Balancer で行う方法を解説します。
Cloud Load Balancer
この記事の対象となるロードバランサーは、グローバル外部アプリケーション ロードバランサ
になります。
旧ロードバランサーや内部ロードバランサー、TCP/IPロードバランサーは対象外です。
(GCSでWebホスティングする為の設定 で公式ドキュメントを元に構築していれば、問題ありません)
ルーティングルールの変更
作ったロードバランサーを編集し、ルーティングルールを変更します。
- 詳細なホストとパスのルールに変更
- ホストとパスのルールを追加
- 新しいホストとパスのルールに、以下を記載して適用
ホスト:*
パスマッチャー:
defaultService: projects/<GCP project id>/global/backendBuckets/<backend bucket name>
name: matcher1
routeRules:
- matchRules:
- pathTemplateMatch: /hogehoge/**
priority: 1
service: projects/<GCP project id>/global/backendBuckets/<backend bucket name>
routeAction:
urlRewrite:
pathTemplateRewrite: /
まとめ
GCSを使ったWebホスティングは、React等のクライアントコンピューティングにとってコストパフォーマンスが高く、とても親和性が良いものになります。
その代わり、こういった痒い所に手を届かす為の設定が必要になります。
今回、Cloud Load Balancer でのURLマッピングの設定に手古摺った為、備忘替わりに記事を作りました。
具体的には、URLマッピング中に以下の事に困りました。
- weightedBackendServices ディレクティブではバックエンドサービスしか使えない為、バックエンドバケットを指定したい時に何を使えばいいか分からない → service ディレクティブでバックエンドバケットを直接指定する
- マッチ文字列にワイルドカードを使いたい場合に、prefixMatch は使えない(regexMatchはインターナルロードバランサーでしか使えない為、pathTemplateMatchを使う必要がある)
以上、皆様の参考になれば幸いです。