Angular 7中有没有一种方法可以在编译时决定使用哪种服务?

时间:2019-04-17 13:26:45

标签: angular ionic-framework build tree-shaking

我已经用Ionic 4创建了一个Angular 7项目。在这个项目中,我有多个环境,例如“本地”或“ firebase”。

在我的环境中。ts是与上面的字符串相对应的参数。

export const environment = {
  production: false,
  ...,
  userApi: 'firebase'
};

我创建了一个模块,以允许按照this article中所述的方式延迟加载我的服务。它看起来如下:

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    AngularFireAuthModule,
    AngularFireModule.initializeApp(environment.firebase),
  ]
})
export class UserApiModule { }

接下来,我有一个InjectionToken,其中声明我在上述模块中提供了服务,并使用工厂决定要使用的服务。

export const USER_SERVICE = new InjectionToken<AbstractUserService>('USER_SERVICE',
    {
        providedIn: UserApiModule,
        factory: UserApiFactory
    }
);

function UserApiFactory(): AbstractUserService {
    switch (environment.userApi) {
        case 'firebase':
            return new FirebaseUserService(inject(AngularFireAuth));
        case 'mock':
            return new MockUserService();
        default:
            throw new Error('UserService implementation not found');
    }
}

通常,此解决方案效果很好。在“ firebase”模式下加载Firebase服务,而在“ local”模式下加载本地服务。

但是,当以“产品”模式编译并提供服务时,ChromeDev-Tools中的程序包大小在两种服务模式下均相同。这使我想到,另一个服务也永远无法访问,仍然在编译。

那么有没有一种方法可以实现此功能,以忽略实际上无法访问的代码?因此,如果我在环境文件中设置了“本地”,firebase服务以及相关性将永远不会包含在构建中?

谢谢!

1 个答案:

答案 0 :(得分:1)

  1. 您可以根据环境配置使用条件导入。有多种方法可以做到,但简单的方法可以是:
@NgModule({
  imports: [ 
       BrowserModule,
       environment.userApi == 'firebase' ? AngularFireAuthModule : []
  ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule {}
  1. 您还可以在环境文件中创建依赖项(导入)数组,并将其添加到导入中,例如(请参阅更多here
imports: [...environment.dependencies]

其中

//environment.ts
dependencies = [
    AngularFireAuthModule,
    AngularFireModule.initializeApp(environment.firebase)
];