简体   繁体   中英

Angular dead code of conditional provider in production bundle

I need to replace a service with a mock service depending on an environment variable. To do this, I used the?-operator in the provider area within my module like this:

@NgModule({
  imports: [
    ...
  ],
  providers: [
    ...
    environment.e2e ? { provide: MyService, useClass: MyServiceMock} : MyService
  ],
})
export class DemoModule {
}

This approach works so far - if the 'e2e' variable is true the mock is used, otherwise the real service is loaded. There is a problem with this solution, however. If I build in production mode (with e2e=false), then the code of the mock is still included in the compiled bundle. I tried also to replace the Service via factory inside the injectable decorator. When using this solution, the service gets replaced in the right way, but the mock is again present in production bundle.

@Injectable({
  providedIn: 'root',
  useFactory: (dep1, dep2) => environment.e2e ? new MyServiceMock(dep1, dep2) : new MyService(dep1, dep2),
  deps: [dep1, dep2]
})
export class MyService {
...
}

Does anyone know a way how I can replace the service depending on the environment and the mock service also doesn't end up in the production bundle?

It feels like the problem of a runtime build variable initialization. If you change environment.e2e to the final value, like true or false , then it works as expected.

For that reason I found only one solution to prevent unuseful code in the final bundle: changes to the angular.json build configurations. You can do file replacements here and it works as you needed:

"fileReplacements": [
  {
    "replace": "src/app/services/my-service.service.ts",
    "with": "src/app/services/mocks/my-service-mock.service.ts"
  },
  ...
],

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