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の設定が必要になります。