toshi-toma blog

主にフロントエンド、作業ログあとは色々なメモ ✍️ 🍅

SPAでページ遷移後にリロードするとページが表示されない ~webpack-dev-server, netlify~

問題

SPAのWebアプリを開発していて、ページ遷移後にブラウザをリロードするとページが表示されない問題が起きました。

この問題は、ローカルの開発環境(webpack-dev-server)を利用している場合と、デプロイ環境(netlify)どちらでも発生しました。

原因は同じで、対応はそれぞれ別で行う必要がありました。
思い返すと、当たり前だなーと思ったりしますが、自分のWebアプリケーションについての理解が不足してました。

原因とそれぞれの対応を書いておきます。

環境

  • react v16.4
  • react-router v4
  • webpack v4
  • webpack-dev-server v3(ローカル環境)
  • Babel v7
  • netlify(デプロイ環境)

原因

原因は、ページ遷移後のURLに対応するルーティングがサーバーサイドで設定されていないので、404(Not Found)となることでした。

例えば、example.com/でindex.htmlを返すようにしたアプリの場合で考えます。
ブラウザで、example.com/にアクセスすると、もちろんindex.htmlが返されて、SPAの場合は概ねbundleしたjsが実行されます。

次に、example.com/hoge/にアクセスした場合、SPAなのでhistory.pushStateというブラウザAPIを使用してURLを変更して画面が切り替わります。 この時、サーバーへはリクエストが飛びません。

そして、この状態(example.com/hoge/)でリロードすると、サーバーに/hogeでリクエストが投げられます。
サーバー側で/hogeのルーティングが無いため、404として処理されるという状況でした。

webpack-dev-serverでの対応

ローカル開発環境(webpack-dev-server)でページ遷移後にリロードすると

Cannot GET /* とエラーが表示されました。

この場合、webpack-dev-serverの設定でpublicPathhistoryApiFallbackを指定しましょう。

const webpack = require('webpack')
const path = require('path')

module.exports = {

  // ...

  output: {
    // ...
    publicPath: '/'   // ← ここ
  },

  // ...
  devServer: {
    historyApiFallback: true   // ← ここ
  }
}

webpack.js.org

これにより、webpack-dev-server上でのアプリのリクエストは404を返す代わりにすべて/index.htmlにリダイレクトするようになります。

publicPathを設定すると、アプリケーション内のすべてのアセットのbase pathを指定できます。
historyAPIFallbackは404を/index.htmlにリダイレクトするようになります。

netlifyでの対応

デプロイ環境(netlify)でページ遷移後にリロードすると

同様に、404 Not Foundが表示されます。

この場合は、netlifyのルーティング設定を追加しましょう。

デプロイ対象となるディレクトリに_redirectsファイルを作成し、以下の内容にします。

/*    /index.html   200

www.netlify.com

これにより、netlifyにデプロイしたアプリのリクエストは404の代わりに/index.htmlにリダイレクトするようになります。

参考にしたページ

tylermcginnis.com

teratail.com