angularfire icon indicating copy to clipboard operation
angularfire copied to clipboard

feat: allow AngularFire to be used in a zoneless angular application

Open eneajaho opened this issue 1 year ago • 16 comments

CleanShot 2024-01-11 at 15 21 30@2x

eneajaho avatar Jan 11 '24 14:01 eneajaho

This issue does not seem to follow the issue template. Make sure you provide all the required information.

google-oss-bot avatar Jan 11 '24 14:01 google-oss-bot

If your app only uses the DI feature of angular/fire, you can build your own providers e.g like that:

import { FirebaseApp, FirebaseOptions, initializeApp } from 'firebase/app';
import { Auth, connectAuthEmulator, getAuth } from 'firebase/auth';
import {
  Firestore,
  connectFirestoreEmulator,
  getFirestore,
} from 'firebase/firestore';
import { createNoopInjectionToken } from 'ngxtension/create-injection-token';

export const [firebaseApp, provideFirebaseApp] =
  createNoopInjectionToken<FirebaseApp>('[Firebase] App');

export const [firestore, provideFirestore] =
  createNoopInjectionToken<Firestore>('[Firebase] Firestore');

export const [firebaseAuth, provideFirebaseAuth] =
  createNoopInjectionToken<Auth>('[Firebase] Auth');

export interface FirebaseConfig {
  options: FirebaseOptions;
  features?: Partial<{
    auth: {
      emulators?: { host: string; port: number };
    };
    firestore: {
      emulators?: { host: string; port: number };
    };
  }>;
}

export function provideFirebase({ options, features }: FirebaseConfig) {
  const app = initializeApp(options);
  const providers = [provideFirebaseApp(app)];

  for (const feature in features) {
    switch (feature) {
      case 'auth': {
        const auth = getAuth(app);
        providers.push(provideFirebaseAuth(auth));

        const emulators = features[feature]?.emulators;

        if (emulators) {
          connectAuthEmulator(
            auth,
            `http://${emulators.host}:${emulators.port}`,
          );
        }

        break;
      }
      case 'firestore': {
        const firestore = getFirestore(app);
        providers.push(provideFirestore(firestore));

        const emulators = features[feature]?.emulators;

        if (emulators) {
          connectFirestoreEmulator(firestore, emulators.host, emulators.port);
        }

        break;
      }
    }
  }

  return providers;
}

RobbyRabbitman avatar Jan 24 '24 14:01 RobbyRabbitman

This is super important, we're about to go zoneless for our app but this is blocking us, unfortunately.

spock123 avatar Jan 29 '24 11:01 spock123

As a workaround, you could provide zoneless change detection for Angular itself and leave zone.js in polyfills for Fire, until it gets sorted out.

vzsolt1981 avatar Feb 05 '24 06:02 vzsolt1981

Hi @vzsolt1981 , that would be worth tryin actually. Thanks, I could try it.

spock123 avatar Feb 05 '24 08:02 spock123

Hi @vzsolt1981 , that would be worth tryin actually. Thanks, I could try it.

Works for me, hence the suggestion. Good luck!

vzsolt1981 avatar Feb 05 '24 08:02 vzsolt1981

Hi @vzsolt1981 , that would be worth tryin actually. Thanks, I could try it.

Works for me, hence the suggestion. Good luck!

How did you actually do it? I have been playing with it a bit, but just adding ZoneJS to @angular/fire did not work - I guess I have to re-build angular/fire again?

In the zones.d.ts, NgZone is imported from @angular/core - how did you deal with all this? Thanks

spock123 avatar Feb 05 '24 08:02 spock123

Hi @vzsolt1981 , that would be worth tryin actually. Thanks, I could try it.

Works for me, hence the suggestion. Good luck!

How did you actually do it? I have been playing with it a bit, but just adding ZoneJS to @angular/fire did not work - I guess I have to re-build angular/fire again?

In the zones.d.ts, NgZone is imported from @angular/core - how did you deal with all this? Thanks

I'm not sure about your approach, it's 2 changes you have to make as per my initial suggestion:

  1. Add (or leave it there) zone.js to polyfills in your app's angular.json (w/o nx) or project.json (w nx):

"polyfills": ["zone.js"],

  1. Add zoneless change detection provider to your app's app.config.ts:
import {
  ApplicationConfig,
  ɵprovideZonelessChangeDetection as provideZonelessChangeDetection,
} from '@angular/core';

export const appConfig: ApplicationConfig = {
  providers: [
    ...,
    provideZonelessChangeDetection(),
  ],
};

vzsolt1981 avatar Feb 05 '24 09:02 vzsolt1981

Hi @vzsolt1981 , that would be worth tryin actually. Thanks, I could try it.

Works for me, hence the suggestion. Good luck!

How did you actually do it? I have been playing with it a bit, but just adding ZoneJS to @angular/fire did not work - I guess I have to re-build angular/fire again? In the zones.d.ts, NgZone is imported from @angular/core - how did you deal with all this? Thanks

I'm not sure about your approach, it's 2 changes you have to make as per my initial suggestion:

  1. Add (or leave it there) zone.js to polyfills in your app's angular.json (w/o nx) or project.json (w nx):

"polyfills": ["zone.js"],

  1. Add zoneless change detection provider to your app's app.config.ts:
import {
  ApplicationConfig,
  ɵprovideZonelessChangeDetection as provideZonelessChangeDetection,
} from '@angular/core';

export const appConfig: ApplicationConfig = {
  providers: [
    ...,
    provideZonelessChangeDetection(),
  ],
};

Can confirm this works well for the moment!

Thanks 🤩

eneajaho avatar Feb 05 '24 10:02 eneajaho

Ahh thanks guys. I had totally removed zonejs in the app. So I guess leave that in polyfills (too bad) but disable it in the config (good).

Cheers

Update: it works, thanks for all the good advice

Update2: it works yes, but it breaks if you are using other libraries that now think ZoneJS provides change detection, which is doesn't. Example: ngx-toastr now thinks ZoneJS exists (it checks I guess) and tries to use that, with an error to follow.

Unfortunately it seems this project is kinda dead-ish, anyone knows if we can use Angular without @angular/fire, and still use Firebase?

spock123 avatar Feb 05 '24 13:02 spock123

@spock123 did you find a solution?

Meistercoach83 avatar May 10 '24 15:05 Meistercoach83

Unfortunately it seems this project is kinda dead-ish, anyone knows if we can use Angular without @angular/fire, and still use Firebase?

You definitely can, if this project doesn't get support we might be heading that way too (Angular with firebase)

lazmeister avatar May 10 '24 15:05 lazmeister

@Meistercoach83 not been able to work on it yet but I don't think there's any issue using the Native firebase library. We use Auth a lot so that part will have to be a bit re-written, as we have used the observable parts as integration with Ngrx/Store.

When I get time and if I make it work I'll make sure to post it here. It's a pity, I really like @angular/fire

spock123 avatar May 10 '24 19:05 spock123

@jamesdaniels is this project dead?

Meistercoach83 avatar May 11 '24 13:05 Meistercoach83

when?

floinay avatar May 25 '24 15:05 floinay

@Meistercoach83 I think he mentioned he's working on adding support for zoneless. Also version 18.0.1 just came out (angular/fire), we've updated and it works well (just not with zoneless yet, but you can go zoneless and add zonejs to polyfills)

We moved away from the 3rd party libraries that broke when zoneJS was missing

spock123 avatar May 27 '24 15:05 spock123