如何在项目和包含的自定义库之间共享 AngularFire 设置



到目前为止,我有一个Angular 7项目,它本身有几个模块,还有我的自定义库,具有外包的通用功能,项目和库都必须使用AngularFire。当我尝试进行下一次设置时遇到的问题是,当我从浏览器访问我的网站时,我会收到这样的错误。

Error: StaticInjectorError(AppModule)[AngularFirestore -> InjectionToken angularfire2.app.options]: 
StaticInjectorError(Platform: core)[AngularFirestore -> InjectionToken angularfire2.app.options]: 
NullInjectorError: No provider for InjectionToken angularfire2.app.options!
at NullInjector.get (core.js:8896)
at resolveToken (core.js:9141)
at tryResolveToken (core.js:9085)
at StaticInjector.get (core.js:8982)
at resolveToken (core.js:9141)
at tryResolveToken (core.js:9085)
at StaticInjector.get (core.js:8982)
at resolveNgModuleDep (core.js:21218)
at _createClass (core.js:21271)
at _createProviderInstance (core.js:21235)

以下是模块的设置:

app.module.ts

import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { AppComponent } from "./app.component";
import { AppRoutingModule } from "./app-routing.module";
import { CoreModule, firebaseConfig } from "./core/core.module";
import { SharedModule } from "./shared/shared.module";
import { FormsModule } from "@angular/forms";
import { HttpClient, HttpClientModule } from "@angular/common/http";
import { TranslateModule, TranslateLoader } from "@ngx-translate/core";
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { NgPipesModule } from "ngx-pipes";
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
import { ChartModule, HIGHCHARTS_MODULES } from "angular-highcharts";
import { ScrollToModule } from "ng2-scroll-to-el";
import { NgCircleProgressModule } from "ng-circle-progress";
import { AngularFireModule } from "@angular/fire";
import { AngularFireAuthModule } from "@angular/fire/auth";
import { AngularFireStorageModule } from "@angular/fire/storage";
import { AngularFirestoreModule } from "@angular/fire/firestore";
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
declare var require: any;
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
SharedModule,
CoreModule,
FormsModule,
NgPipesModule,
HttpClientModule,
BrowserAnimationsModule,
NgbModule,
ChartModule,
AngularFireModule.initializeApp(firebaseConfig),
AngularFireAuthModule,
AngularFireStorageModule,
AngularFirestoreModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
NgCircleProgressModule.forRoot({}),
ScrollToModule.forRoot()
],
providers: [
{
provide: HIGHCHARTS_MODULES,
useFactory: () => [require("highcharts/highcharts-more.src")]
} // add as factory to your providers
],
bootstrap: [AppComponent]
})
export class AppModule {}

Core.module.ts:

import {
Compiler,
COMPILER_OPTIONS,
CompilerFactory,
NgModule
} from "@angular/core";
import { JitCompilerFactory } from "@angular/platform-browser-dynamic";
import { registerLocaleData } from "@angular/common";
import localeUk from "@angular/common/locales/uk";
registerLocaleData(localeUk);
import { HeaderComponent } from "./header/header.component";
import { AppRoutingModule } from "../app-routing.module";
import { SharedModule } from "../shared/shared.module";
import { CoreRoutingModule } from "./core-routing.module";
import { MainAreaComponent } from "./main-area/main-area.component";
import { TranslateModule } from "@ngx-translate/core";
import { StrengthsService } from "./strengths.service";
import { ScoreCardsService } from "./score-cards.service";
import { GroupsService } from "./groups.service";
import { StudentsService } from "./students.service";
import { TutorsService } from "./tutors.service";
import { SubjectsService } from "./subjects.service";
import { ConditionsService } from "./conditions.service";
import { ChartsDataService } from "./charts/charts-data.service";
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
import { SettingsService } from "./settings.service";
import { AuthService, TCoreModule } from "@eriendel/t-core";
import { environment } from "../../environments/environment";
export function createCompiler(fn: CompilerFactory): Compiler {
return fn.createCompiler();
}
export const firebaseConfig = environment.firebaseConfig;
@NgModule({
declarations: [HeaderComponent, MainAreaComponent],
imports: [
SharedModule,
AppRoutingModule,
CoreRoutingModule,
TranslateModule.forChild(),
NgbModule,
TCoreModule.forChild({
autoAuthRoleCredentials: environment.autoAuthRoleCredentials
})
],
exports: [AppRoutingModule, HeaderComponent],
providers: [
{
provide: COMPILER_OPTIONS,
useValue: {},
multi: true
},
{
provide: CompilerFactory,
useClass: JitCompilerFactory,
deps: [COMPILER_OPTIONS]
},
{
provide: Compiler,
useFactory: createCompiler,
deps: [CompilerFactory]
},
ScoreCardsService,
StrengthsService,
GroupsService,
StudentsService,
TutorsService,
SubjectsService,
ConditionsService,
ChartsDataService,
SettingsService,
AuthService
]
})
export class CoreModule {}

还有我的库t-core.module.ts的模块:

import { ModuleWithProviders, NgModule, LOCALE_ID } from "@angular/core";
import { HTTP_INTERCEPTORS, HttpClient } from "@angular/common/http";
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
import { RouterModule } from "@angular/router";
import { CommonModule, registerLocaleData } from "@angular/common";
import localeUk from "@angular/common/locales/uk";
registerLocaleData(localeUk);
import { TranslateLoader, TranslateModule } from "@ngx-translate/core";
import { LoggingInterceptor } from "./logging.interceptor";
import { NotFoundComponent } from "./not-found/not-found.component";
import { SidebarComponent } from "./sidebar/sidebar.component";
import { AuthService } from "./auth.service";
import { DatesService } from "./dates.service";
import { LocalizationService } from "./localization.service";
import { CalculationsService } from "./calculations/calculations.service";
import { NavService } from "./nav.service";
import { SigninComponent } from "./auth/signin/signin.component";
import { ChangePassComponent } from "./auth/change-pass/change-pass.component";
import { AntiAuthGuard } from "./auth/antiAuth.guard";
import {
AuthGuard,
AutoAuthRoleCredential,
AUTO_AUTH_ROLE_CREDENTIALS
} from "./auth.guard";
import { FormsModule } from "@angular/forms";
import { HttpLoaderFactory } from "./HttpLoaderFactory";
import { UIModule } from "./ui/ui.module";
import { AngularFireModule, FirebaseAppConfig } from "@angular/fire";
import { AngularFireAuthModule, AngularFireAuth } from "@angular/fire/auth";
import {
AngularFirestoreModule,
AngularFirestore
} from "@angular/fire/firestore";
import { AngularFireStorageModule } from "@angular/fire/storage";
export interface TCoreModuleConfig {
autoAuthRoleCredentials: AutoAuthRoleCredential[];
}
// @dynamic
@NgModule({
declarations: [
NotFoundComponent,
SidebarComponent,
SigninComponent,
ChangePassComponent
],
imports: [
RouterModule,
CommonModule,
FormsModule,
UIModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
NgbModule
],
exports: [
SidebarComponent,
NotFoundComponent,
SigninComponent,
ChangePassComponent
]
})
export class TCoreModule {
static forRoot(config: TCoreModuleConfig): ModuleWithProviders {
return {
ngModule: TCoreModule,
providers: [
AuthService,
CalculationsService,
DatesService,
LocalizationService,
NavService,
AntiAuthGuard,
AuthGuard,
{
provide: AUTO_AUTH_ROLE_CREDENTIALS,
useValue: config.autoAuthRoleCredentials
},
{
provide: HTTP_INTERCEPTORS,
useClass: LoggingInterceptor,
multi: true
},
{
provide: LOCALE_ID,
deps: [LocalizationService],
useFactory: localizationService =>
localizationService.getLocale()
},
AngularFirestore,
AngularFireAuth
]
};
}
static forChild(config: TCoreModuleConfig): ModuleWithProviders {
return this.forRoot(config);
}
}

所以我看到的问题是我不可能在我的底层库模块中初始化 AngularFireModule。为此,我必须在 t 核心模块的导入部分中提供 firebase 配置,并且只能在 t 核心模块类的 forRoot() 方法中注入,这为时已晚,无法导入 AFAIK。

还有其他方法可以做到这一点吗?

我也很难让它工作。我找到了一个令人惊讶的解决方案。下面是该解决方案的最小复制。

简而言之,我不直接在库模块中初始化甚至包含 Angular Fire。我初始化并仅将其包含在应用程序模块中。似乎库模块可以自动利用 Angular Fire,一旦所有内容都导入到应用程序模块中并使用应用程序模块进行编译。

下面是相关代码的视图:

库模块

shared.module.ts

我预计需要在此文件中初始化 Angular Fire,但任何这样做的尝试都会导致失败。最终,我尝试只包括来自Angular Fire的AngulrFireAuthAngularFirestoreAngularFireDatabase模块,而不是基本AngularFireModule。这奏效了。然后我尝试从库中删除所有 AngularFire 模块,这也有效。这些似乎以对等依赖方式运行,其中库不需要直接包含在其模块中的 Angular Fire 模块依赖项,只要它们包含在实际运行的模块中即可。

import { NgModule } from '@angular/core'

@NgModule({
declarations: [],
imports: [
],
exports: []
})
export class SharedModule { }

shared.service.ts

此文件利用AngularFireAuth服务,即使AngularFireAuthModule尚未包含在库模块中也是如此。

import { Injectable } from '@angular/core'
import { AngularFireAuth } from '@angular/fire/auth'
import { map } from 'rxjs/operators'
@Injectable({
providedIn: 'root'
})
export class SharedService {
constructor(
private fireAuth: AngularFireAuth
) { }
getClaims$() {
return this.fireAuth.idTokenResult.pipe(
map(idTokenResult => (idTokenResult || { claims: null }).claims)
)
}
}

应用模块

app.module.ts

在这个文件中,我们最终初始化并包含 AngularFireModule 以及库模块 (SharedModule)。出于某种原因,我从来不必包含AngularFireAuthModule来使其工作。

import { AppComponent } from './app.component'
import { SharedModule } from 'shared'
import { AngularFireModule } from '@angular/fire'
import { environment } from '../environments/environment'
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
SharedModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

在此文件中,我们使用库模块(SharedService)中的服务从AngularFireAuth服务获取用户声明。

import { Component } from '@angular/core'
import { Observable } from 'rxjs'
import { SharedService } from 'shared'
@Component({
selector: 'app-root',
styles: [],
template: `
<h1>Hello.</h1>
<pre *ngIf="(claims$ | async) as claims">let claims = {{ claims | json }}</pre>
`
})
export class AppComponent {
claims$: Observable<any>
constructor(
private auth: SharedService
) { }
ngOnInit() {
this.claims$ = this.auth.getClaims$()
}
}

您是否在 angular 应用中设置了 Firebase 环境? 1)转到您的火力基地控制台 2)选择项目->项目设置 3)在那里你会得到这样的东西:-> var firebaseConfig 对象从那里

4)复制它并将其粘贴到您的angular_project_folder->src->环境->环境中,如下所示

导出常量环境 = {obj}

最新更新