react-routerを使ったアプリケーションでURL直叩き(or F5)すると404になる
はじめに
こんにちは、だいきちです。
今回はreact-router
を使用し、serve
を使ってローカルにサーバを立てた時
/
以外のURLで404となってしまう現象について書きます。
恐らくタイトルだけ見て「ははぁ~ん?」となった方もいるでしょう
ですが、私は初学者ゆえわからず・・・
結果としては公式ドキュメントちゃんと読めよ
という話でした。(自戒
環境
- create-react-app(CRA) : 2.1.3
- react-router: 4.3.1
- serve: 11.0
なぜ404?
この辺りを参照。
qiita.com
要するに、サーバ側にrewrite
の設定が必要な訳ですね。
2つ目のQ&Aを見るとわかると思いますが、サーバ側が返しているのはあくまでindex.html
react-routerがURLに対応するコンポーネントを切り替えているだけなので、
URLにマッチするリソースは存在しません = 404となるわけですね。
なるほど、わかりやすい。
Reactって動的にindex.htmlを書き換えてるだけですもんね、仮想DOMを使って。
(間違ってたらスミマセン)
解決策
で、本題の解決策なんですが、ぶっちゃけるとserve
では解決してません。
serveのREADME
見るとそれっぽいこと は書いてあるのですが
まず
create-react-app
の公式ドキュメントにそれっぽいことは書いてないか?
という疑問が浮かんだので、調べると...
ありました
なになに...
If you use routers that use the HTML5 pushState history API under the hood (for example, React Router with browserHistory), many static file servers will fail. google様訳: HTML5 pushState history APIを内部で使用するルーター(たとえば、browserHistoryを持つReact Router)を使用すると、多くの静的ファイルサーバーが失敗します。
ですよねー
と、いうわけで下の方に行くと、Express
を使用した例が。
素直にExpress
をインストールして使用しました。
npm install express --save
その後、プロジェクトルートにserver.js
を作成。
後は公式ドキュメントのソースをコピペ。
const express = require('express'); const path = require('path'); const app = express(); app.use(express.static(path.join(__dirname, 'build'))); app.get('/*', function(req, res) { res.sendFile(path.join(__dirname, 'build', 'index.html')); }); app.listen(9000);
npm run build
でアプリケーションをビルド。
node server.js
でサーバ起動。http://localhost:9000
に接続すれば
アプリケーションの起動が確認できると思います。
後はURLを直叩きしても404にならない優しい世界をご堪能下さい。
余談
先ほどserve
では実装しませんでしたが、やはりconfigっぽいのを定義すればいけるんじゃないでしょうか。
(下記参照。※検証はしていません。)
spectrum.chat
まとめ
最初にも書きましたが、公式ドキュメントは読みましょう。
もう一度言います、公式ドキュメントは読みましょう
現場からは以上です。