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 服务以及依赖项永远不会包含在构建中?
提前致谢!
- 您可以根据您的环境配置使用条件导入。有多种方法可以做到这一点,但一个简单的方法是:
@NgModule({
imports: [
BrowserModule,
environment.userApi == 'firebase' ? AngularFireAuthModule : []
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
- 您还可以在环境文件中创建依赖项(导入)数组,并将它们添加到导入中,例如(查看更多 here:
imports: [...environment.dependencies]
哪里
//environment.ts
dependencies = [
AngularFireAuthModule,
AngularFireModule.initializeApp(environment.firebase)
];
我用 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 服务以及依赖项永远不会包含在构建中?
提前致谢!
- 您可以根据您的环境配置使用条件导入。有多种方法可以做到这一点,但一个简单的方法是:
@NgModule({
imports: [
BrowserModule,
environment.userApi == 'firebase' ? AngularFireAuthModule : []
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
- 您还可以在环境文件中创建依赖项(导入)数组,并将它们添加到导入中,例如(查看更多 here:
imports: [...environment.dependencies]
哪里
//environment.ts
dependencies = [
AngularFireAuthModule,
AngularFireModule.initializeApp(environment.firebase)
];