Angular environment files do not get swapped in time

1.3k views Asked by At

I am using Angular 9, View Engine compiler.

I have 2 files where I store environment values:

environment.ts:

export const environment: any = {
    production: false,
};

environment.prod.ts:

export const environment: any = {
    production: true
}

Here is a part of my angular.json configuration that swaps environment.ts with environment.prod.ts when building the app for production environment:

"configurations": {
    "production": {
      "fileReplacements": [
        {
          "replace": "app/src/environments/environment.ts",
          "with": "app/src/environments/environment.prod.ts"
        }
      ]
    }
  }

I am using environment variables to configure the third-party service if it should or should not run on developer mode. However, in production (when building with --prod flag), it was not working properly. After some investigation we have found out that the third party service is getting the value from environment.ts and not from the environment.prod.ts.

Here is the trimmed down version of app.module.ts where the configuration is made:

import { environment } from './../environments/environment';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    // Google Analytics (via Angulartics2)
    Angulartics2Module.forRoot({
      developerMode: !environment.production // <-- Gets incorrect value: 'true' on production mode
    }),                                      // but should be 'false'
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor() {
    console.log(!environment.production); // <-- Logs correct value: 'false' on production mode
  }
}

Later testing at runtime that Angulartics2 third-party service indeed received the wrong value:

@Injectable({ providedIn: 'root' })
export class GoogleAnalyticsService {
  constructor(
    private angulartics2: Angulartics2
  ) {
    console.log(this.angulartics2.settings.developerMode); // Logs 'true'
  }
}

Why is the wrong environment value being received in AppModule's @NgModule decorator function, but then - the correct one in AppModule's constructor and the service that executes later at runtime? Does the @NgModule() decorator function for AppModule gets executed before the environment files get swapped by the compiler?

1

There are 1 answers

0
mcvyty On BEST ANSWER

It seems Angular uses Webpack for file replacements specified in Angular.json. So the file replacement happens at some point in the build phase, which is probably after the code in decorators such as @NgModule gets resolved by the Angular compiler. Thus, it seems one should not use environment variables when configuring @NgModule imports.