AngularFire error only when ng serve --prod

2020-08-13 05:33发布

问题:

I have an Angular 8 app, using npm package Angular Firebase (https://github.com/angular/angularfire2) and when I build the app with the Angular CLI command ng build --prod and deploy to my hosting I get the following Chrome Browser Console error:

TypeError: Object(...)(...).auth is not a function

If I instead build with the command ng build --prod --optimization=false the error does not occur.

Something with Angular CLI ng build option optimization set to true is causing the AngularFire2 npm package error.

I am not sure how to debug this issue further. Here is my package.json file:

    {
  "name": "bigmoenyshot",
  "version": "8.0.0",
  "license": "https://themeforest.net/licenses/terms/regular",
  "scripts": {
    "ng": "ng",
    "serve": "ng serve",
    "serveProd": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --prod --optimization=true",
    "build": "ng build --prod=true --aot=true --extractCss=true --optimization=true",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "deploy": "ng build --prod=true --aot=true --extractCss=true --optimization=false && firebase deploy"
  },
  "private": true,
  "dependencies": {
    "@agm/core": "1.0.0-beta.2",
    "@angular/animations": "8.0.0",
    "@angular/cdk": "8.0.1",
    "@angular/common": "8.0.0",
    "@angular/compiler": "8.0.0",
    "@angular/core": "8.0.0",
    "@angular/fire": "^5.2.1",
    "@angular/flex-layout": "8.0.0-beta.26",
    "@angular/forms": "8.0.0",
    "@angular/material": "8.0.1",
    "@angular/material-moment-adapter": "^8.0.2",
    "@angular/platform-browser": "8.0.0",
    "@angular/platform-browser-dynamic": "8.0.0",
    "@angular/router": "8.0.0",
    "@ngu/carousel": "1.5.4",
    "@ngx-translate/core": "10.0.1",
    "@ngx-translate/http-loader": "3.0.1",
    "@swimlane/ngx-datatable": "15.0.2",
    "angular-calendar": "0.26.4",
    "angular-in-memory-web-api": "0.8.0",
    "angular-star-rating": "4.0.0-beta.3",
    "chart.js": "2.5.0",
    "classlist.js": "1.1.20150312",
    "core-js": "2.4.1",
    "css-star-rating": "1.2.4",
    "date-fns": "1.28.5",
    "echarts": "4.2.1",
    "firebase": "^6.2.4",
    "flag-icon-css": "3.3.0",
    "hammerjs": "2.0.8",
    "highlight.js": "9.15.6",
    "hopscotch": "0.3.1",
    "install": "0.12.2",
    "moment": "2.24.0",
    "ng2-charts": "2.2.2",
    "ng2-dragula": "2.1.1",
    "ng2-file-upload": "1.3.0",
    "ng2-validation": "4.2.0",
    "ngx-color-picker": "7.5.0",
    "ngx-echarts": "4.1.1",
    "ngx-pagination": "3.2.1",
    "ngx-perfect-scrollbar": "^8.0.0",
    "ngx-quill": "4.8.0",
    "npm": "6.9.0",
    "perfect-scrollbar": "1.4.0",
    "quill": "1.3.6",
    "rxjs": "6.5.2",
    "rxjs-compat": "6.1.0",
    "web-animations-js": "github:angular/web-animations-js#release_pr208",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^0.800.6",
    "@angular-devkit/core": "7.3.8",
    "@angular/cli": "8.0.2",
    "@angular/compiler-cli": "8.0.0",
    "@angular/language-service": "8.0.0",
    "@types/hopscotch": "0.2.30",
    "@types/jasmine": "2.5.38",
    "@types/node": "6.0.60",
    "codelyzer": "^5.0.1",
    "copy-webpack-plugin": "4.3.0",
    "enhanced-resolve": "3.3.0",
    "jasmine-core": "~2.5.2",
    "jasmine-spec-reporter": "~3.2.0",
    "karma": "~1.4.1",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "~0.2.0",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "~0.2.2",
    "node-sass": "^4.12.0",
    "protractor": "~5.1.0",
    "ts-node": "2.0.0",
    "tslint": "4.5.0",
    "typescript": "3.4.5"
  }
}

And here is where I import the AngularFire2 Lib:

import { Injectable } from '@angular/core';
import { AngularFireAuth } from "@angular/fire/auth";
import { Observable } from 'rxjs';
import { tap, map, take } from 'rxjs/operators';
import { Router } from '@angular/router';
import { User, auth } from 'firebase/app';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  user: Observable<User>

  constructor(
    private firBase: AngularFireAuth,
    private router: Router // Inject Firebase auth service
  ) {
    this.user = this.firBase.authState;
  }

  isLoggedIn(redirectUrl: string, isLoggedInRedirect?: string): Observable<boolean> {
    console.log('AuthService.isLoggedIn'); return this.user.pipe(
      take(1),
      map(authState => !!authState),
      tap(authenticated => {
        if (!authenticated) {
          console.log('user not authenticated');
          this.router.navigate([redirectUrl]);
          return;
        }
        console.log('user Authenticated');
        if (isLoggedInRedirect) {
          this.router.navigate([isLoggedInRedirect]);
        }
      })
    );
  }

  getDisplayName(): string {
    return this.firBase.auth.currentUser.displayName;
  }

  // Sign up with email/password
  async signUp(email: string, password: string) {
    try {
      const result = await this.firBase.auth.createUserWithEmailAndPassword(email, password);
      console.log("successfully registered!");
      console.log(result.user);
    }
    catch (error) {
      console.error(error.message);
    }
  }

  // Sign in with email/password
  async signIn(email: string, password: string, rememberMe: boolean): Promise<string> {
    let session = 'session'; //only persist in the current session or tab, and will be cleared when the tab or window in which the user authenticated is closed

    if (rememberMe) {
      session = 'local'; //state will be persisted even when the browser window is closed or the activity
    }

    console.log('persistence type', session);
    try {
      const _ = await this.firBase.auth.setPersistence(session);
      const result = await this.firBase.auth.signInWithEmailAndPassword(email, password);
      console.log('signin success');
      return 'success';
    }
    catch (error) {
      console.error(error.message);
      return error.message;
    }
  }

  async signOut() {
    try {
      const _ = await this.firBase.auth.signOut();
      this.user = this.firBase.authState;
      console.log('signOut complete, currentUser', this.firBase.auth.currentUser);
    }
    catch (error) {
      console.error(error.message);
    }
  }

  async forgotPassword(email: string): Promise<string> {
    try {
      await this.firBase.auth.sendPasswordResetEmail(email);
      return 'Reset Email Sent';
    }
    catch (error) {
      console.error(error.message);
      return error.message;
    }
  }
}

And here is my app.module:

import { NgModule, ErrorHandler } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BrowserModule, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { GestureConfig } from '@angular/material';
import {
  PerfectScrollbarModule,
  PERFECT_SCROLLBAR_CONFIG,
  PerfectScrollbarConfigInterface
} from 'ngx-perfect-scrollbar';


import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './shared/inmemory-db/inmemory-db.service';

import { rootRouterConfig } from './app.routing';
import { SharedModule } from './shared/shared.module';
import { AppComponent } from './app.component';

import { HttpClient, HttpClientModule } from '@angular/common/http';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { ErrorHandlerService } from './shared/services/error-handler.service';
import { SessionsModule } from './views/sessions/sessions.module';

import { AngularFireModule } from '@angular/fire';
//import { AngularFirestoreModule } from '@angular/fire/firestore';
import { environment } from '../environments/environment';
import { StartComponent } from './start.component';

// AoT requires an exported function for factories
export function HttpLoaderFactory(httpClient: HttpClient) {
  return new TranslateHttpLoader(httpClient);
}

const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = {
  suppressScrollX: true
};

@NgModule({
  imports: [
    SessionsModule,
    BrowserModule,
    BrowserAnimationsModule,
    SharedModule,
    AngularFireModule.initializeApp(environment.firebase),
    //AngularFirestoreModule,
    HttpClientModule,
    PerfectScrollbarModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    }),
    InMemoryWebApiModule.forRoot(InMemoryDataService, { passThruUnknownUrl: true }),
    RouterModule.forRoot(rootRouterConfig, { useHash: true, enableTracing: false })
  ],
  declarations: [AppComponent, StartComponent],
  providers: [
    { provide: ErrorHandler, useClass: ErrorHandlerService },
    { provide: HAMMER_GESTURE_CONFIG, useClass: GestureConfig },
    { provide: PERFECT_SCROLLBAR_CONFIG, useValue: DEFAULT_PERFECT_SCROLLBAR_CONFIG }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

回答1:

It's not the complete answer, it just my research. Which I'm putting here, hope it helps someone.

Check this command

node --max-old-space-size=8000 ./node_modules/@angular/cli/bin/ng build --prod --aot=false --optimization=true --sourceMap=false --buildOptimizer=false

Comment: Can you please! remove AOT flag or make it false?

Reference: https://github.com/angular/angular-cli/issues/14666#issuecomment-507057022


buildOptimizer is not working anymore

--buildOptimizer=false

Reference: https://github.com/angular/angular-cli/issues/10658#issuecomment-387296781

Reference: https://github.com/angular/angular-cli/issues/10655#issuecomment-449319049


  • --source-map generate 10% smaller app

Reference: https://github.com/angular/angular-cli/issues/11129#issuecomment-396274621


  • set target to es5, build target es2015 have these issues

Reference: https://github.com/datorama/akita/issues/179#issuecomment-472505123

Reference: https://github.com/angular/angular-cli/issues/7799#issuecomment-387167797



回答2:

Had the same issue with AngularFireFunctions. Managed to solve it by adding AngularFireFunctionsModule to my app.module.ts. Just turn on sourceMaps for your prod build, so you can debug which library is actually broken. Turns out that without the module everything will work fine in development, but when you build with --prod flag optimizer removes parts of the code it shouldn't and there are loose ends left.



回答3:

according to @jamesdaniels answer this

npm install rxjs@6 rxjs-compat@6 --save

It solved the issue.

and this is Your Solution Credit @Biswajit



回答4:

Solved this by importing the firebase dependencies I was using on the component with error, you can do something like that:

import * as firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/storage';
import 'firebase/firestore';
import { environment } from '../../../environments/environment';

constructor(
    private afAuth: AngularFireAuth,
    private afFirestore: AngularFirestore,
    private afStorage: AngularFireStorage
  ) {
    try {
      firebase.app();
    } catch (err) {
      firebase.initializeApp(environment.firebaseConfig);
    }
}

Dont forget to place your firebase configs at your environment file



回答5:

I had the same problem. Going back to

"@angular/fire": "~5.1.0",

solved the problem, although there're some warnings about version incompatibilities with other packages (no compilation or runtime errors).



回答6:

In My case, having the AngularFireAuthModule, and AngularFirestoreModule in app.module.ts worked since I was using both of those in my app.

imports: [
    ...
    AngularFireAuthModule,
    AngularFirestoreModule,
    ...],