How to migrate Flutter project to Firebase version-9 modern web modular style

727

Solution 1

Your flutter code does not follow what the docs suggest, especially where and how Firebase.initializeApp(); is called.

Here's a snippet directly from the docs:

import 'package:flutter/material.dart';

// Import the firebase_core plugin
import 'package:firebase_core/firebase_core.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(App());
}

/// We are using a StatefulWidget such that we only create the [Future] once,
/// no matter how many times our widget rebuild.
/// If we used a [StatelessWidget], in the event where [App] is rebuilt, that
/// would re-initialize FlutterFire and make our application re-enter loading state,
/// which is undesired.
class App extends StatefulWidget {
  // Create the initialization Future outside of `build`:
  @override
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  /// The future is part of the state of our widget. We should not call `initializeApp`
  /// directly inside [build].
  final Future<FirebaseApp> _initialization = Firebase.initializeApp();

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      // Initialize FlutterFire:
      future: _initialization,
      builder: (context, snapshot) {
        // Check for errors
        if (snapshot.hasError) {
          return SomethingWentWrong();
        }

        // Once complete, show your application
        if (snapshot.connectionState == ConnectionState.done) {
          return MyAwesomeApp();
        }

        // Otherwise, show something whilst waiting for initialization to complete
        return Loading();
      },
    );
  }
}

As you can see, that function is called after runApp(App()); has been called. Not only does Firebase.initializeApp(); return a Future<FirebaseApp> (which you do not await in your code), it is part of the main widget's state.

Solution 2

The Flutter Web bindings for Firebase are built on top of the pre-v9 API. As far as I can see in the Github repo, no discussion has been started on porting them to v9 yet. I'd recommend leaving it to the library's authors to decide when the best time is to migrate to the v9 modular API style, and use v8 until then as shown in the FlutterFire documentation on adding the Firebase SDKs to your web app.

If you insist on migrating to v9 already, you can use its -compat builds, which bolts the previous API style on the new modular version. This will allow you to work with the latest builds, although it will not give you the (full) size benefits of the new modular API.

Share:
727
Mithson
Author by

Mithson

Computer Science Enthusiast learning to be good at problem solving Interested in creation of mobile application, web app, desktop apps and embedded systems. Skilled in logic, Algebra and Discrete maths. I am well versed in Python, C, SQL, Javascript, Flutter, Java, Angular, HTML, CSS, Linux, Algorithms and Data structure Handy with softwares like netbeans, Android studio, vscode and Visual studio.

Updated on January 01, 2023

Comments

  • Mithson
    Mithson over 1 year

    I am facing problem with initializing the Firebase and Flutter project, while I just updated my firebase-tools and firebase to version 9 which is modern web modular style and its been a week nothing has helped the documentation of flutter is still according to version 8 which is old style compat type and when I follow firebase documentation which is updated its throwing errors with flutter. I need your help firebase and flutter experts please provide some solution.

    The two error which I get are,

    core.dart:56 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'app')
        at Object.app$ [as app] (core.dart:56)
        at initializeApp (firebase_core_web.dart:68)
        at initializeApp.next (<anonymous>)
        at runBody (async_patch.dart:84)
        at Object._async [as async] (async_patch.dart:123)
        at firebase_core_web.FirebaseCoreWeb.new.initializeApp (firebase_core_web.dart:28)
        at initializeApp (firebase.dart:42)
        at initializeApp.next (<anonymous>)
        at runBody (async_patch.dart:84)
        at Object._async [as async] (async_patch.dart:123)
        at Function.initializeApp (firebase.dart:38)
        at main$ (main.dart:9)
        at main$.next (<anonymous>)
        at runBody (async_patch.dart:84)
        at Object._async [as async] (async_patch.dart:123)
        at main$ (main.dart:7)
        at main (web_entrypoint.dart:19)
        at main.next (<anonymous>)
        at async_patch.dart:45
        at _RootZone.runUnary (zone.dart:1613)
        at _FutureListener.thenAwait.handleValue (future_impl.dart:155)
        at handleValueCallback (future_impl.dart:707)
        at Function._propagateToListeners (future_impl.dart:736)
        at _Future.new.[_completeWithValue] (future_impl.dart:542)
        at future.dart:401
        at _RootZone.runUnary (zone.dart:1613)
        at _FutureListener.then.handleValue (future_impl.dart:155)
        at handleValueCallback (future_impl.dart:707)
        at Function._propagateToListeners (future_impl.dart:736)
        at _Future.new.[_completeWithValue] (future_impl.dart:542)
        at async._AsyncCallbackEntry.new.callback (future_impl.dart:580)
        at Object._microtaskLoop (schedule_microtask.dart:40)
        at _startMicrotaskLoop (schedule_microtask.dart:49)
        at async_patch.dart:166
    

    and

    ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
    js_primitives.dart:30 The following JSNoSuchMethodError was thrown building MyApp(dirty):
    js_primitives.dart:30 TypeError: Cannot read properties of undefined (reading 'app')
    js_primitives.dart:30 
    js_primitives.dart:30 The relevant error-causing widget was:
    js_primitives.dart:30   MyApp file:///C:/Users/Neha/AndroidStudioProjects/devcom/lib/main.dart:10:10
    js_primitives.dart:30 
    js_primitives.dart:30 When the exception was thrown, this was the stack:
    js_primitives.dart:30 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 236:49  throw_
    js_primitives.dart:30 packages/firebase_core_web/firebase_core_web.dart 73:3                                                                     _catchJSError
    js_primitives.dart:30 packages/firebase_core_web/src/firebase_core_web.dart 138:13                                                               app
    js_primitives.dart:30 packages/firebase_core/src/firebase.dart 55:41                                                                             app
    js_primitives.dart:30 packages/firebase_auth/src/firebase_auth.dart 38:47                                                                        get instance
    js_primitives.dart:30 packages/devcom/auth.dart 12:51                                                                                            new
    js_primitives.dart:30 packages/devcom/main.dart 17:13                                                                                            build
    js_primitives.dart:30 packages/flutter/src/widgets/framework.dart 4648:28                                                                        build
    js_primitives.dart:30 packages/flutter/src/widgets/framework.dart 4574:15                                                                        performRebuild
    js_primitives.dart:30 packages/flutter/src/widgets/framework.dart 4267:5                                                                         rebuild
    js_primitives.dart:30 packages/flutter/src/widgets/framework.dart 4553:5                                                                         [_firstBuild]
    js_primitives.dart:30 packages/flutter/src/widgets/framework.dart 4548:5                                                                         mount
    js_primitives.dart:30 packages/flutter/src/widgets/framework.dart 3611:13                                                                        inflateWidget
    js_primitives.dart:30 packages/flutter/src/widgets/framework.dart 3363:18                                                                        updateChild
    js_primitives.dart:30 packages/flutter/src/widgets/binding.dart 1189:16                                                                          [_rebuild]
    js_primitives.dart:30 packages/flutter/src/widgets/binding.dart 1159:5                                                                           mount
    js_primitives.dart:30 packages/flutter/src/widgets/binding.dart 1104:16                                                                          <fn>
    js_primitives.dart:30 packages/flutter/src/widgets/framework.dart 2535:19                                                                        buildScope
    js_primitives.dart:30 packages/flutter/src/widgets/binding.dart 1103:12                                                                          attachToRenderTree
    js_primitives.dart:30 packages/flutter/src/widgets/binding.dart 936:24                                                                           attachRootWidget
    js_primitives.dart:30 packages/flutter/src/widgets/binding.dart 917:7                                                                            <fn>
    js_primitives.dart:30 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19       internalCallback
    js_primitives.dart:30 
    js_primitives.dart:30 ════════════════════════════════════════════════════════════════════════════════════════════════════
    

    main.dart:

    import 'package:flutter/material.dart';
    import 'package:devcom/auth.dart';
    import 'package:devcom/auth_provider.dart';
    import 'package:devcom/root_page.dart';
    import 'package:firebase_core/firebase_core.dart';
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      Firebase.initializeApp();
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return AuthProvider(
          auth: Auth(),
          child: MaterialApp(
            title: 'Flutter login demo',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: RootPage(),
          ),
        );
      }
    }
    

    index.html :

    <!DOCTYPE html>
      <html>
      <head>
        <!-- <script src="https://www.gstatic.com/firebasejs/9.0.1/firebase-app.js" type = "module"></script>
        <script src="https://www.gstatic.com/firebasejs/9.0.1/firebase-analytics.js" type = "module"> </script>
        <script src="https://www.gstatic.com/firebasejs/9.0.1/firebase-auth.js" type = "module"></script> -->
        <meta charset="UTF-8">
        <meta content="IE=Edge" http-equiv="X-UA-Compatible">
        <meta name="description" content="A new Flutter project.">
      
        <!-- iOS meta tags & icons -->
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black">
        <meta name="apple-mobile-web-app-title" content="devcom">
        <link rel="apple-touch-icon" href="icons/Icon-192.png">
      
        <!-- Favicon -->
        <link rel="shortcut icon" type="image/png" href="favicon.png" />
      
        <title>Devcom</title>
        <link rel="manifest" href="manifest.json">
      </head>
    <body >
      <!-- The core Firebase JS SDK is always required and must be listed first -->
     
    <script type="module"> 
      import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.0.1/firebase-app.js';
      import {  } from 'https://www.gstatic.com/firebasejs/9.0.1/firebase-auth.js';
      import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.0.1/firebase-analytics.js";
    
    
        const firebaseConfig = {
         apiKey: "...",
          authDomain: "......",
          databaseURL: ".....",
          projectId: "...",
          storageBucket: "",
          messagingSenderId: "",
          measurementId: "",
          appId: "1:.........:web:...........",
        };
        
        const app = initializeApp({ firebaseConfig });
    // const app = getAnalytics({ firebaseConfig })    
    </script>
     
     <script>
        var serviceWorkerVersion = null;
        var scriptLoaded = false;
        function loadMainDartJs() {
          if (scriptLoaded) {
            return;
          }
          scriptLoaded = true;
          var scriptTag = document.createElement('script');
          scriptTag.src = 'main.dart.js';
          scriptTag.type = 'application/javascript';
          document.body.append(scriptTag);
        }
    
        if ('serviceWorker' in navigator) {
          // Service workers are supported. Use them.
          window.addEventListener('load', function () {
            // Wait for registration to finish before dropping the <script> tag.
            // Otherwise, the browser will load the script multiple times,
            // potentially different versions.
            var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
            navigator.serviceWorker.register(serviceWorkerUrl)
              .then((reg) => {
                function waitForActivation(serviceWorker) {
                  serviceWorker.addEventListener('statechange', () => {
                    if (serviceWorker.state == 'activated') {
                      console.log('Installed new service worker.');
                      loadMainDartJs();
                    }
                  });
                }
                if (!reg.active && (reg.installing || reg.waiting)) {
                  // No active web worker and we have installed or are installing
                  // one for the first time. Simply wait for it to activate.
                  waitForActivation(reg.installing ?? reg.waiting);
                } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
                  // When the app updates the serviceWorkerVersion changes, so we
                  // need to ask the service worker to update.
                  console.log('New service worker available.');
                  reg.update();
                  waitForActivation(reg.installing);
                } else {
                  // Existing service worker is still good.
                  console.log('Loading app from service worker.');
                  loadMainDartJs();
                }
              });
    
            // If service worker doesn't succeed in a reasonable amount of time,
            // fallback to plaint <script> tag.
            setTimeout(() => {
              if (!scriptLoaded) {
                console.warn(
                  'Failed to load app from service worker. Falling back to plain <script> tag.',
                );
                loadMainDartJs();
              }
            }, 4000);
          });
        } else {
          // Service workers not supported. Just drop the <script> tag.
          loadMainDartJs();
        }
      </script>
     
    </body>
    </html>
  • Mithson
    Mithson over 2 years
    I am new to firebase, so how can I downgrade my firebase version to the version which flutter supports which is currently I guess 8.6.1 or use comat version-9 of firebase with flutter
  • Mithson
    Mithson over 2 years
    does uninstalling the Firebase with npm and installing again insures that it will be compatible version with Flutter or we need to specify it
  • Frank van Puffelen
    Frank van Puffelen over 2 years
    The documentation I linked shows exactly what to add, which is indeed version 8.6.1, like <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.j‌​s"></script>. Once you do that, you can also use the code snippet to initialize Firebase that is shown on that page.
  • Mithson
    Mithson over 2 years
    I did what you suggested now every errors are gone but the now its executing the first if statement with condition snapshot.hasError and returning SomethingWentWrong() code
  • Mithson
    Mithson over 2 years
    thanks man Its working now problem cause was 'auth' in main.dart