Angular 7 中有没有办法在编译时决定使用哪个服务?

Is there a way in Angular 7 to decide at compile time which service to use?

我用 Ionic 4 创建了一个 Angular 7 项目。在这个项目中我有多个环境,例如 'local' 或 'firebase'。

在我的environment.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' 模式下加载本地服务。

但是 在 'prod' 模式下编译和服务时,ChromeDev-Tools 中的包大小在任一服务模式下都是相同的。这让我想到,另一个服务仍然无法访问,但仍在编译中。

那么有没有办法实现这个功能来忽略实际上无法访问的代码呢?因此,如果我在我的环境文件中设置 'local',firebase 服务以及依赖项永远不会包含在构建中?

提前致谢!

  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)
];