Azure Static Web AppsにデプロイしたSPAのルーティング設定

SPA(Single Page Application)は、React Router などのルーターや History API を用いることで、URLパスに応じた画面を表示できます。(別の視点では、画面遷移に応じてURLパスが変化します)

そうして作成したWebアプリをAzure Static Web Appsにデプロイした際に、ルーティング周りで発生した問題と解決方法を記します。

発生した問題

React Routerで次のようなルーティングを設定しました。

React
<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エラーが出ます。

ログイン画面やアプリ利用中に更新ボタンを押すだけで「ページが存在しません」などと言われて困惑しました。

https://***.azurestaticapps.net/login → エンター! よし! (よくない)

原因

ブラウザで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 を作成して、以下の内容を記述するだけです。

staticwebapp.config.json
{
  "navigationFallback": {
    "rewrite": "/index.html"
  }
}

ここでは全てのリクエストに対して/index.htmlを返しています。
あとはReact Routerがルーティングして適切な画面を表示します。解決!

ちなみにAzure Static Web Appsでルーティングを実現する手段として他に routes.json ファイルを用いる方法がありますが、非推奨(deprecated)になりました


staicwebapp.config.json にはフォールバック以外にも様々な設定項目があります。
サーバの一部リソース(画像など)だけはリクエストを許可したり、認証状態に応じたアクセス制限なども設定可能なようです。
設定項目の一つとして、非推奨になった routes.json の役割を取り込んだ形でしょうか。
これからも学習していきます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA