SPA(Single Page Application)は、React Router などのルーターや History API を用いることで、URLパスに応じた画面を表示できます。(別の視点では、画面遷移に応じてURLパスが変化します)
そうして作成したWebアプリをAzure Static Web Appsにデプロイした際に、ルーティング周りで発生した問題と解決方法を記します。
発生した問題
React Routerで次のようなルーティングを設定しました。
<Router>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/map/:mapId" element={<AppMain/>} />
<Route path="/error" element={<ErrorPage />} />
<Route path="*" element={<ErrorPage />} />
</Routes>
</Router>
アプリをローカルマシンで実行中、次のようなURLをブラウザに直接打ち込んでアクセスすることで、そのパスに対応するUIが表示されることを確認しました。
- http://localhost:xxxx
→ErrorPage - http://localhost:xxxx/login
→LoginPage - http://localhost:xxxx/map/123
→AppMain - http://localhost:xxxx/error
→ErrorPage - http://localhost:xxxx/example
→ErrorPage
さて、このアプリをAzure Static Web Appsにデプロイしました。
発行されたURLはhttps://***.azurestaticapps.net
といった感じです。
ページ内の操作によるページ遷移は問題なく動作します。表示されているURLもそれに追従します。
ところがルート以外のURLを直打ちしたり更新したりしてアクセスすると404エラーが出ます。
ログイン画面やアプリ利用中に更新ボタンを押すだけで「ページが存在しません」などと言われて困惑しました。
原因
ブラウザでURLにアクセスするとリクエストが飛び、そのアドレスのリソースを取得しようとします。
つまりhttps://***.azurestaticapps.net/login
にアクセスすると/login
のリソースをリクエストしますが、当然そこにファイルはないので404エラーを返します。
これが原因でした。
ちなみにhttps://***.azurestaticapps.net/
にアクセスした場合にリクエストされるのはhttps://***.azurestaticapps.net/index.html
でありファイルが存在していたため、ルートだけは表示できていたのです。
またページ内操作でのページ遷移はReact Router(History API)によってリクエストが制御されているためこれも動作します。
解決方法
Azure Static Web Appsの設定で、リソースがないリクエストのフォールバック先を指定すればOKです。
設定ファイル staicwebapp.config.json を作成して、以下の内容を記述するだけです。
{
"navigationFallback": {
"rewrite": "/index.html"
}
}
ここでは全てのリクエストに対して/index.html
を返しています。
あとはReact Routerがルーティングして適切な画面を表示します。解決!
ちなみにAzure Static Web Appsでルーティングを実現する手段として他に routes.json ファイルを用いる方法がありますが、非推奨(deprecated)になりました。
staicwebapp.config.json にはフォールバック以外にも様々な設定項目があります。
サーバの一部リソース(画像など)だけはリクエストを許可したり、認証状態に応じたアクセス制限なども設定可能なようです。
設定項目の一つとして、非推奨になった routes.json の役割を取り込んだ形でしょうか。
これからも学習していきます。