React routerで制作したサイトをApache公開すると404になる

react + react routerでアプリを作成して、ビルド後にApacheで公開するとルーティングがうまくいかずに404が発生することがあります。

開発時にwebpack-dev-serverなどを利用してデバックしていると気が付きませんが、ビルド後のbuild.jsをwebサーバー(Apache)にアップして確認するとページリロード時などに404が発生します。

シングルページアプリケーション(SPA)なのでwebサーバの設定が必要です。

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のリクエストを投げる必要があります。

httpd.confの設定

httpd.confを編集して.htaccessを使用できるように設定します。

<Directory />
  AllowOverride none
</Directory>

AllowOverrideをAllに変更します。

<Directory />
  AllowOverride All
</Directory>

各オプションはの意味は下記です。

None
.htaccessを無効にします
All
.htaccessで指定した全ディレクティブの使用を許可します。
AuthConfig
認証に関するディレクティブを許可します。
Limit
ホスト名やIPアドレスによるアクセス制御を許可します。
FileInfo
ディレクトリ表示の設定を許可します。mod_rewriteはこの設定になります
Indexes
ディレクトリインデックスに関するディレクティブの使用を許可します。
Options
Options指定子で設定する機能を許可します。

.htaccessならFileInfoでいけるかもですが、私はいつもAllにしています。

セキュリティとか気になるならFileInfoで試してください。

あと設定するディレクトリも「Directory /」で全て許可していますが、

「Directory “/subdir”」などで、特定のディレクトリのみ指定することもできます。

リダイレクト設定

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

関連記事
最新記事