在Angular 9项目中,我正在使用两种环境:生产和模拟。
在核心模块中,我检查模拟环境。
如果构建是通过模拟配置进行的,我将注入返回模拟数据的模拟服务,因此不会发出外部http请求。
如果使用产品配置进行构建,则会注入真实服务。
我这样做是这样的:
@NgModule({
declarations: [],
providers: [],
imports: [BrowserModule, HttpClientModule],
exports: [],
})
export class CoreModule {}
const countryServiceFactory = (
_http: HttpClient,
_errorUtil: ErrorUtilService
) => {
return isMock
? new ServiceMock()
: new Service(_http, _errorUtil);
};
@Injectable({
providedIn: CoreModule,
useFactory: countryServiceFactory,
})
export abstract class CountryServiceProxy {
abstract getCountries(): Observable<CountryWithLanguages[]>;
}
ServiceMock
和Service
实现相同的接口。
这有效。
代码不可可摇树。结果是在我的捆绑包中(当我运行ng build --prod
时)甚至包括了模拟服务。
我想在开发过程中将每个服务从模拟切换到生产。
如何使Angular仅捆绑将要使用的服务?
我正在使用:
Angular CLI: 9.0.4
Node: 13.6.0
OS: darwin x64
Ivy Workspace: Yes
谢谢! :)
答案 0 :(得分:2)
我刚刚尝试了一种似乎可行的方法:
environment.{env}.ts
文件中声明相关的服务工厂我的测试设置:
基类
@Injectable()
export abstract class TestService {
abstract environment: string;
}
开发服务
@Injectable()
export class DevTestService extends TestService {
environment = 'qwertydev';
}
产品服务
@Injectable()
export class ProdTestService extends TestService {
environment = 'qwertyprod';
}
environment.ts
export const environment = {
testServiceFactory: () => new DevTestService()
};
environment.production.ts
export const environment = {
testServiceFactory: () => new ProdTestService()
};
app.module.ts
providers: [
{ provide: TestService, useFactory: environment.testServiceFactory }
],
app.component.ts
constructor(private testService: TestService) {}
ngOnInit() {
console.log(this.testService.get());
}
当我检查构建文件时,我仅在开发版本中发现qwertydev
,而在生产版本中发现qwertprod
,这表明它们已经摇晃了。
我使用字符串qwerty*
使缩小后的构建文件搜索变得容易。
在模块中声明服务
我已经在模块中声明了提供程序,以避免循环引用。通过将服务声明为providedIn: Module
,很容易引入循环引用。
您可以通过声明第三方模块来解决此问题,但这似乎有些过分。
我已经在较旧的答案中证明了这一点:@Injectable() decorator and providers array
替代方法
在环境文件中声明服务工厂并不完全正确。我只是为了简单而进行测试。您可以创建自己的一组特定于环境的文件,这些文件在构建时会以与环境文件相同的方式被覆盖,但是坦率地说,这听起来像是一场噩梦。