firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.53k stars 3.93k forks source link

🐛 [firebase_core_web] flutterfire_ignore_scripts and firebase_core is not defined #12204

Open mwoelk opened 6 months ago

mwoelk commented 6 months ago

Bug report

Describe the bug To comply with GDPR we are not allowed to load any scripts from a third party domain such as *.gstatic.com. Because in this case, the IP address of the user which is deemed personal information is handed over to a third party without the users consent.

Because of this, I wanted to use flutterfire_ignore_scripts as described in the setup docs.

I downloaded the js files and added them to my web/index.html.

    <script src="./vendor/firebase-app.js"></script>
    <script src="./vendor/firebase-messaging.js"></script>

I also added the following line before flutter gets loaded.

window.flutterfire_ignore_scripts = ["core", "messaging"];

Now I get an error in the console stating firebase_core is not defined

Steps to reproduce

Steps to reproduce the behavior:

  1. Add firebase + firebase messaging to the project
  2. download the firebase-app.js and firebase-messaging.js scripts and add them manually to web/index.html
  3. Add the window.flutterfire_ignore_scriptsline to the file as well
  4. Build and open the web app. Check the console to see the error

Expected behavior

firebase_core should be defined when manually including the scripts.

Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand ``` Doctor summary (to see all details, run flutter doctor -v): [!] Flutter (Channel stable, 3.13.5, on macOS 14.2.1 23C71 darwin-x64, locale en-DE) ! Warning: `dart` on your path resolves to /usr/local/Cellar/dart/3.0.4/libexec/bin/dart, which is not inside your current Flutter SDK checkout at /Users/woelkmax/fvm/versions/3.13.5. Consider adding /Users/woelkmax/fvm/versions/3.13.5/bin to the front of your path. [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 15.2) [✓] Chrome - develop for the web [✓] Android Studio (version 2022.3) [✓] VS Code (version 1.85.1) [✓] Connected device (4 available) [✓] Network resources ! Doctor found issues in 1 category. ```
danagbemava-nc commented 6 months ago

Hi @mwoelk, would it be possible to provide a complete minimal reproducible code sample in a repo that we can clone so that we can investigate this?

I tried to reproduce with the steps outlined above, but I don't see the firebase_core is not defined error (I tested with the firebase_core example app).

Thank you

mwoelk commented 6 months ago

Hi @danagbemava-nc,

Sure. I cloned the repo and modified the firebase_core example app to ignore the scripts and added a copy of https://www.gstatic.com/firebasejs/10.7.2/firebase-app-compat.js into the example (according to the docs - just had to use the *-compat.js version otherwise I get an export not found).

The error message shown in the console is different if you run in debug or release.

In debug (flutter run -d chrome) i get this error when clicking on the Initialize default app-Button:

Uncaught (in promise) Error: [core/not-initialized] Firebase has not been correctly initialized.

Usually this means you've attempted to use a Firebase service before calling `Firebase.initializeApp`.

In release (flutter run --release -d chrome) I get the error:

firebase_core is not defined
mwoelk commented 6 months ago

I guess it's because the dart implementation expects a window.firebase_<package> object that isn't set when just including the script and is otherwise set automatically by the injection script.

mwoelk commented 6 months ago

When I use the following, the previous errors disappear but instead I alway get a Service messaging is not available error. I won't get that error with automatic injection.

It seems like when th files get injected automatically there is something more going on than just importing the files.

<script type="module">
      import * as core from "./vendor/firebase-app.js";
      import * as messaging from "./vendor/firebase-messaging.js";

      window["firebase_core"] = core;
      window["firebase_messaging"] = messaging;

      window.flutterfire_ignore_scripts = ["core", "messaging"];
</script>
danagbemava-nc commented 5 months ago

Hi @mwoelk, thanks for the clarification in https://github.com/firebase/flutterfire/issues/12204#issuecomment-1911969645. I was able to see the same error. But it seems like that issue has been resolved(?). When do you get this issue in https://github.com/firebase/flutterfire/issues/12204#issuecomment-1912328027?

mwoelk commented 5 months ago

He @danagbemava-nc , unfortunately the issue is not resolved yet. I wasn't able to import/set-up the external scripts in a way that would work exactly like the default auto-injection logic. It seems to me that there is some additional set-up / scoping going on when the scripts are injected through the dart code. So the code above just changes the initial error message to another error but won't.

The "Service messaging is not available" error is thrown when I try to call FirebaseMessaging.instance.getToken() in my flutter application. It seems like the messaging script isn't properly detected/initialized when I import the scripts as shown above. There is no error when I use auto-injection.

So my best guess would be that there is some scoping issues going on.

danagbemava-nc commented 5 months ago

Thanks for the details.

I am not particularly familiar with this area so I will be labeling this for further insight from the team.

cc @russellwheatley

mwoelk commented 5 months ago

Ok. Guess I found some more information. The problem is that the CDN script for firebase-messaging contains an absolute import for the firebase-app from the CDN.:

import{registerVersion as e,_registerComponent as t,_getProvider,getApp as n}from"https://www.gstatic.com/firebasejs/10.8.0/firebase-app.js";

This leads the browser to fetch another version of firebase-app which of course is uninitalized. I had to modify my downloaded file and make the import relative so it uses the downloaded firebase-app that was importet and initialized before.

I guess either the docs need to be updated or the CDN files should be using relative imports ;)