You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ionic7集成AngularFire Auth出现NullInjectorError依赖缺失问题

Ionic7 + AngularFire 认证:InjectionToken angularfire2.app.options 缺失问题

我正在用Ionic7和AngularFire实现Firebase认证,网上大部分教程都是旧版的app.module.ts配置方式,现在已经不适用了,所以我自定义了FirebaseModule:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { provideAuth, getAuth } from '@angular/fire/auth';
import { provideFirestore, getFirestore } from '@angular/fire/firestore';

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "XXXXX",
  ...
};


@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    provideFirebaseApp(
      () => initializeApp(firebaseConfig)), 
      provideAuth(() => getAuth()), 
      provideFirestore(() => getFirestore(),
  ),
  ],
  providers: []
})
export class FirebaseModule { }

并编写了认证服务AuthenticationServiceService:

//reference https://www.positronx.io/ionic-firebase-authentication-tutorial-with-examples/

import { Injectable, NgZone } from '@angular/core';
import {
  AngularFirestore,
  AngularFirestoreDocument,
} from '@angular/fire/compat/firestore';
import { AngularFireAuth } from '@angular/fire/compat/auth';
import { Router } from '@angular/router';
import { User } from './modal/user.modal';
import * as auth from 'firebase/auth';

@Injectable({
  providedIn: 'root'
})
export class AuthenticationServiceService {
  userData: any;

  constructor( public afStore: AngularFirestore,
    public ngFireAuth: AngularFireAuth,
    public router: Router,
    public ngZone: NgZone) {
      this.ngFireAuth.authState.subscribe((user) => {
        if (user) {
          this.userData = user;
          localStorage.setItem('user', JSON.stringify(this.userData));
          JSON.parse(localStorage.getItem('user') || '{}');
        } else {
          localStorage.setItem('user', null || '{}');
          JSON.parse(localStorage.getItem('user') || '{}');
        }
      });
     }

     // Returns true when user is looged in
  get isLoggedIn(): boolean {
    const user = JSON.parse(localStorage.getItem('user') || '{}');
    return user !== null && user.emailVerified !== false ? true : false;
  }
  // Returns true when user's email is verified
  get isEmailVerified(): boolean {
    const user = JSON.parse(localStorage.getItem('user') || '{}');
    return user.emailVerified !== false ? true : false;
  }
  // Sign in with Gmail
  GoogleAuth() {
    return this.AuthLogin(new auth.GoogleAuthProvider());
  }

  // Auth providers
  AuthLogin(provider: any) {
    return this.ngFireAuth
      .signInWithPopup(provider)
      .then((result) => {
        this.ngZone.run(() => {
          this.router.navigate(['dashboard']);
        });
        this.SetUserData(result.user);
      })
      .catch((error) => {
        window.alert(error);
      });
  }

  // Store user in localStorage
  SetUserData(user: any) {
    const userRef: AngularFirestoreDocument<any> = this.afStore.doc(
      `users/${user.uid}`
    );
    const userData: User = {
      uid: user.uid,
      email: user.email,
      displayName: user.displayName,
      photoURL: user.photoURL,
      emailVerified: user.emailVerified,
    };
    return userRef.set(userData, {
      merge: true,
    });
  }

  // Sign-out
  SignOut() {
    return this.ngFireAuth.signOut().then(() => {
      localStorage.removeItem('user');
      this.router.navigate(['login']);
    });
  }
  
}

随后在独立组件Tab1Page中引入FirebaseModule并注入该服务:

import { FirebaseModule } from '../firebase/firebase.module';
import { AuthenticationServiceService } from '../authentication-service.service';

@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss'],
  standalone: true,
  imports: [IonicModule, CommonModule, FirebaseModule, FormsModule, ReactiveFormsModule],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class Tab1Page {
  constructor(public authService: AuthenticationServiceService) {}
}

但运行时出现如下错误:

ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(Standalone[Tab1Page])[AuthenticationServiceService -> AuthenticationServiceService -> AuthenticationServiceService -> AuthenticationServiceService -> AngularFirestore -> InjectionToken angularfire2.app.options -> InjectionToken angularfire2.app.options]: 
  NullInjectorError: No provider for InjectionToken angularfire2.app.options!
NullInjectorError: R3InjectorError(Standalone[Tab1Page])[AuthenticationServiceService -> AuthenticationServiceService -> AuthenticationServiceService -> AuthenticationServiceService -> AngularFirestore -> InjectionToken angularfire2.app.options -> InjectionToken angularfire2.app.options]: 
  NullInjectorError: No provider for InjectionToken angularfire2.app.options!
    at NullInjector.get (core.mjs:7493:27)
    at R3Injector.get (core.mjs:7914:33)
    at R3Injector.get (core.mjs:7914:33)
    at injectInjectorOnly (core.mjs:618:33)
    at Module.ɵɵinject (core.mjs:622:60)
    at Object.AngularFirestore_Factory [as factory] (angular-fire-compat-firestore.js:584:102)
    at R3Injector.hydrate (core.mjs:8015:35)
    at R3Injector.get (core.mjs:7903:33)
    at injectInjectorOnly (core.mjs:618:33)
    at Module.ɵɵinject (core.mjs:622:60)
    at resolvePromise (zone.js:1211:31)
    at resolvePromise (zone.js:1165:17)
    at zone.js:1278:17
    at _ZoneDelegate.invokeTask (zone.js:406:31)
    at core.mjs:23896:55
    at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:23896:36)
    at _ZoneDelegate.invokeTask (zone.js:405:60)
    at Object.onInvokeTask (core.mjs:24197:33)
    at _ZoneDelegate.invokeTask (zone.js:405:60)
    at Zone.runTask (zone.js:178:47)

问题原因

你混用了AngularFire的模块化API(provideFirebaseApp等)和兼容层API(AngularFireAuth、AngularFirestore),导致依赖注入不匹配。兼容层需要传统的AngularFireModule.initializeApp()配置,而不是新的provideFirebaseApp。

修复方案

方案1:调整FirebaseModule支持兼容层

修改FirebaseModule,添加兼容层模块的初始化,这是让AngularFireAuth和AngularFirestore正常工作的关键:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
// 导入兼容层模块
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireAuthModule } from '@angular/fire/compat/auth';
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
// 保留新的模块化API(可选)
import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { provideAuth, getAuth } from '@angular/fire/auth';
import { provideFirestore, getFirestore } from '@angular/fire/firestore';

const firebaseConfig = {
  apiKey: "XXXXX",
  // 你的其他配置项
};

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    // 兼容层初始化,必须添加
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFireAuthModule,
    AngularFirestoreModule,
    // 新的模块化API可以保留,两者不冲突
    provideFirebaseApp(() => initializeApp(firebaseConfig)),
    provideAuth(() => getAuth()),
    provideFirestore(() => getFirestore())
  ],
  providers: []
})
export class FirebaseModule { }

方案2:迁移到纯模块化API(推荐)

兼容层会逐渐被官方淘汰,建议直接使用AngularFire的新模块化API,修改认证服务如下:

import { Injectable, NgZone } from '@angular/core';
import { Auth, signInWithPopup, GoogleAuthProvider, signOut, authState } from '@angular/fire/auth';
import { Firestore, doc, setDoc } from '@angular/fire/firestore';
import { Router } from '@angular/router';
import { User } from './modal/user.modal';

@Injectable({
  providedIn: 'root'
})
export class AuthenticationServiceService {
  userData: any;

  constructor(
    private auth: Auth,
    private firestore: Firestore,
    private router: Router,
    private ngZone: NgZone
  ) {
    authState(this.auth).subscribe((user) => {
      if (user) {
        this.userData = user;
        localStorage.setItem('user', JSON.stringify(this.userData));
        JSON.parse(localStorage.getItem('user') || '{}');
      } else {
        localStorage.setItem('user', '{}');
        JSON.parse(localStorage.getItem('user') || '{}');
      }
    });
  }

  get isLoggedIn(): boolean {
    const user = JSON.parse(localStorage.getItem('user') || '{}');
    return user !== null && user.emailVerified !== false;
  }

  get isEmailVerified(): boolean {
    const user = JSON.parse(localStorage.getItem('user') || '{}');
    return user.emailVerified !== false;
  }

  GoogleAuth() {
    return this.AuthLogin(new GoogleAuthProvider());
  }

  AuthLogin(provider: any) {
    return signInWithPopup(this.auth, provider)
      .then((result) => {
        this.ngZone.run(() => {
          this.router.navigate(['dashboard']);
        });
        this.SetUserData(result.user);
      })
      .catch((error) => {
        window.alert(error);
      });
  }

  async SetUserData(user: any) {
    const userRef = doc(this.firestore, `users/${user.uid}`);
    const userData: User = {
      uid: user.uid,
      email: user.email,
      displayName: user.displayName,
      photoURL: user.photoURL,
      emailVerified: user.emailVerified,
    };
    await setDoc(userRef, userData, { merge: true });
  }

  SignOut() {
    return signOut(this.auth).then(() => {
      localStorage.removeItem('user');
      this.router.navigate(['login']);
    });
  }
}

这种情况下,你的原始FirebaseModule配置可以保持不变,不需要导入任何兼容层模块。

方案3:确认独立组件配置

无论采用哪种方案,Tab1Page的imports数组中保留FirebaseModule即可,无需额外修改。


内容的提问来源于stack exchange,提问作者Moblize IT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:17:01