🥵

【firebase x flutter web】動的ルーティング時のtips

2024/02/04に公開

この記事でわかること

  • firebase hostingでホスティングしているflutter webにおいて、動的ルーティングの実装後、アクセスするとCannot GET XXX/xxxとなる問題の解決策

発生した問題

前提条件

  • flutter web(firebaseでホスティング)
  • 利用パッケージ
    • GoRouter: flutterにルーティングを実装するパッケージ
  • ディレクトリ
- lib
 - main.dart
- firebase.json

コード

main.dart
// flutter内蔵パッケージ
import 'package:flutter/material.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:go_router/go_router.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_service/firebase_options.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  setUrlStrategy(PathUrlStrategy());
  runApp(MainApp());
}

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  
  Widget build(BuildContext context) {
    final rootNavigatorKey = GlobalKey<NavigatorState>();
    final homeNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'home');
    final favorireNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'favorite');
    final settingNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'account');
    final router = GoRouter(
      navigatorKey: rootNavigatorKey,
      initialLocation: '/',
      routes: [
        StatefulShellRoute.indexedStack(
          parentNavigatorKey: rootNavigatorKey,
          builder: (context, state, navigationShell) =>
              AppNavigationBar(navigationShell: navigationShell),
          branches: [
            // home
            StatefulShellBranch(
              navigatorKey: homeNavigatorKey,
              routes: [
                GoRoute(
                  path: '/',
                  builder: (context, state) =>
                      const Text('Home'),
                  routes: [
                    GoRoute(
                      path: 'example1/:name',
                      builder: (context, state) {
                        final String name = state.pathParameters['name']!;
                        return Text(name);
                      },
                    ),
                    GoRoute(
                      path: 'example2/:name',
                      builder: (context, state) {
                        final String name = state.pathParameters['name']!;
                        return Text(name);
                      },
                    ),
                  ],
                ),
              ],
            ),

            // favorite
            StatefulShellBranch(
              navigatorKey: favorireNavigatorKey,
              routes: ...
            ),

            // setting
            StatefulShellBranch(
              navigatorKey: settingNavigatorKey,
              routes: ...
            ),
          ],
        ),
      ],
    );

    return MaterialApp.router(
      title: 'sample',
      routerConfig: router,
    );
  }
}

やったこと

  • {XXXXX}/example1/aaaにアクセスする

期待した結果

  • 画面上にaaaと表示される

実際の結果

  • Cannot GET /example1/aaaと表示される

発生原因

  • ルートディレクトリ直下のfirebase.jsonの設定忘れ
    • ルート以外にアクセス(ここでは/example1/aaa)しても、aaaというファイルは存在しないため、エラーが発生する

解決策

  • 全てのリクエストに対して、index.htmlを返すように、firebase.jsonを書き換える
firebase.json
{
  "hosting": {
    "source": ".",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "frameworksBackend": {
      "region": "asia-east1"
    },
+   "rewrites": [
+     {
+       "source": "**",
+       "destination": "/index.html"
+     }
+   ]
  },
  ...
}

参考文献

https://www.kamo-it.org/blog/24/
https://pub.dev/documentation/go_router/latest/go_router/RouteBase-class.html

Discussion