react + react routerでアプリを作成して、ビルド後にApacheで公開するとルーティングがうまくいかずに404が発生することがあります。
開発時にwebpack-dev-serverなどを利用してデバックしていると気が付きませんが、ビルド後のbuild.jsをwebサーバー(Apache)にアップして確認するとページリロード時などに404が発生します。
404の原因
下記のようなURLがあるとします。
https://test.jp/profile
index.html(reactトップ)からlink toでprofileに移動する際はreact routerが機能してindex.htmlのページ内容をprofileのページに書き換えます。(SPA)
しかし、URLが「https://test.jp/profile」の時にブラウザをリロードすると、ブラウザがApacheに「https://test.jp/profile」のリクエストを投げます。
Apacheはドキュメントルート以下の(/var/www/htmlなど)のprofileというディレクトリを探します。
SPAで作成されたreactにはprofileとか実際のディレクリやファイルは存在しないはずです。
当然ページが見つからないので404を返します。not foundです。
react routerを機能させるにはindex.html(reactトップ)にhttps://test.jp/profileのリクエストを投げる必要があります。
リダイレクト設定
Apacheに来たリクエストをindex.html(reactトップ)に投げれば解決です。
リダイレクトには.htaccessを使用します。
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [QSA,L]
上記の設定を書き込んだ.htaccessをApacheのドキュメントルートに設置します。
※mod_rewriteが利用できることが前提です。
解説
RewriteEngine On
リライトを有効にします。
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCondでルールの適用条件を指定します。
!-fは%{REQUEST_FILENAME}のファイルが存在しない場合。
!-dは%{REQUEST_FILENAME}のディレクトリが存在しない場合。
RewriteRule ^ index.html [QSA,L]
RewriteCondが全てtrueならRewriteRuleでindex.htmlにリダイレクトします。
[QSA]はクエリストリング(?var=1)などを引き継ぐ。
[L]は処理はここで終了。
まとめ
上記の設定を.htaccessにするとディレクトリやファイルが存在しないときはindex.htmlにリダイレクトされます。
URLは変わりませんので、react-routerが機能して意図したページが表示されます。
reactなどSPAのアプリをルーティングする際はApacheの設定が必要になります。