react を使って SPA を構築した場合、静的リソースが存在しない URL を直接指定すると 404 Error になる
この記事の概要(忙しい方はここだけ見れば良いです)
react-router のルーティング設定だけでは、静的リソースの存在しないページを直接 URL で指定してアクセスすると 404 Error になります。 URL を直接指定しても目的のページを表示させるようにするには、サーバでフォールバックを設定しましょう。webpack-dev-server であるならば historyApiFallback: true を設定することで、404 Error を回避できます。
react-router のルーティングはあくまでクライアント上での(サーバーにリクエストを送らない)ページ遷移に用いられるもので、サーバの方で routing が設定されている OR 静的リソースが存在しないページへのアクセスは 404 Error になります。routing が設定されていない(静的リソースが存在しない)ページがサーバに要求された場合、トップレベルの URL (http://localhost/ ) のコンテンツをクライアントに返した後で、react-router による遷移がなされるような(フォールバック)設定をする必要があります。
詳細説明
環境
frontend: react + redux backend: nodejs (webpack-dev-server)
状況
- http://localhost -> 200 OK -> react による http://localhost/error への遷移 -> 適切なエラー画面の表示
- http://localhost/error にアクセス -> react-router で設定したはずのエラー画面が表示されず 404 Error
原因の詳細
https://teratail.com/questions/26245:react-routerでURLパラメータを指定した際、URL直打ちだと404になります から引用
トップページから react-router でページを辿る場合以下の遷移になりますが、 http://hoge.com/ http://hoge.com/index.html => 実際ブラウザが読み込んでいるのはこのファイル http://hoge.com/detail/1 => react-router が対応するコンポーネントを読み込んで表示。このとき History API により URL が書き換わっている ブラウザリロード、またはダイレクトにアクセスした場合、以下のようになります。 http://hoge.com/detail/1 => このリソースは存在しないので 404 になる したがって、リソースが存在しない場合 /index.html に rewrite してあげないといけないはずです。rewrite の設定ができている場合、ダイレクトにアクセスした場合の挙動は以下のようになります。 http://hoge.com/detail/1 http://hoge.com/index.html => URLが rewrite された結果ブラウザが読み込んでいるのはこのファイルになる http://hoge.com/detail/1 => react-router が対応するコンポーネントを読み込んで表示
解決方法
webpack.config.js の devServer に "historyApiFallback: true" を追加する
devServer: { historyApiFallback: true, contentBase: 'www', port: 4000, inline: true }
これで存在しないリソースに対するアクセスは、/index.html に フォールバックされるようになります。
参考