简体   繁体   中英

Angular: Weird if statement behaviour in app.module.ts


we recently experienced weird behaviour in our app.module.ts. We were using environment.ts and environemnt.prod.ts file to include/exclude specific library in imports array of the module(library should be excluded for production build). It looked something like this:

import { environment } from '../environments/environment'
//
@NgModule({
//
  imports: [
    CommonModule,
    BrowserModule,
    environment.production ? [] : libraryXXX,
    HttpClientModule,
    FormsModule
  ],

we found out after days of barren investigation that libraryXXX is included in build every time, even with --prod flag. We tested what's the problem - the value from environment.ts/prod.ts file was read correctly, but for whatever reason comparision always returned false. What I mean by always: replacing above fragment with:

environment.production == true ? [] : libraryXXX

or

environment.production == false ? [] : libraryXXX

did not change a thing - library WAS ALWAYS included. Like the if statement was broken(?). Extracting it to variable didn't change a thing. We ended up doing semi-hacky solution like:

environment.ts

import { libraryXXX } from 'whatever'

export const environment = {
  production: false,
  libraryXXX: libraryXXX
}

environment.prod.ts

export const environment = {
  production: true,
  libraryXXX: []
}

and simply referening to environment.libraryXXX in app.module.ts. But out of the curiosity - can anyone explain to me why simple if statement failed? Since it was app.module.ts I could not debug it, or even see console output, to know what's going on. Anyone has an idea?

This will work.

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

const targetModules = [
    CommonModule,
    BrowserModule,
    HttpClientModule,
    FormsModule
];

if (environment.production) {
   targetModules.push(libraryXXX);
}

//
@NgModule({
//
  imports: targetModules,
//

What you can do:

You can import both libraries, the prod and the mock version.

Then you can decide (environment.production) which of both your will provide:

providers: [
   {
      provide: DbTrassenanfrageStatusService,
      useClass: environment.production ? XyzMockService : XyzService
   }
]

If you are talking about modules: Give this a try:

const exports = [];
if (environment.production === true) {
  exports.push(ModuleXyyyz);
  console.info('FactoryModule: ModuleXyyyz;');
} else {
  console.info('FactoryModule: nothing;');
}

@NgModule({
  imports: [
    ModuleXyyyz
  ],
  exports
})
export class FactoryModule {
}

Then import FactoryModule in your app module.

To 'choose' the environment.prod.ts config, just build or start it via --prod flag:

ng serve --prod
ng build --prod

See the angular cli doc for more information (--prod, --configuration, ...)

If you have an environment.*.ts like this:

export const environment = {
    production: true,
    env: 'prod',
    version: '{BUILD_VERSION}',
    commitHash: '{COMMIT_HASH}',
    showVersionIndicator: false,
    routerTracing: false,

...then you can print out a field like version at startup (in your app component):

console.info('Version: ', environment.version);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM