在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
谢谢! :)
我尝试了一种可行的解决方案,使用interceptor返回模拟,而不使用服务工厂。
CoreModule具有生产提供者和拦截器
@NgModule({
declarations: [],
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: IntegrationsMockInterceptorService,
multi: true,
},],
imports: [BrowserModule, HttpClientModule],
exports: [],
})
export class CoreModule {}
我定义了一个拦截器
const isMock = environment.mock;
const mockResults = [
{
url: API_COUNTRY_URL,
mock: GET_COUNTRIES_MOCK,
},
];
@Injectable()
export class IntegrationsMockInterceptorService implements HttpInterceptor {
intercept<T>(
req: HttpRequest<T>,
next: HttpHandler
): Observable<HttpEvent<T>> {
if (!isMock) {
return next.handle(req);
}
const mock = this._getMockByUrl(req.url);
return of(new HttpResponse({ status: 200, body: (mock as unknown) as T }));
}
private _getMockByUrl(url: string) {
const result = mockResults.find(result => result.url === url);
if (!result) {
console.error(`Mock not defined for url:${url}`);
}
return result?.mock;
}
}
使用拦截器的捆绑包更大。
我进行了在拦截器中定义5个模拟服务和5个元素的实验。
模拟对象(mockResults[].mock
内部包含在主捆绑包中。
chunk {1} main-es2015.5e8588ae9917478e9732.js (main) 656 kB [initial] [rendered]
chunk {1} main-es5.5e8588ae9917478e9732.js (main) 772 kB [initial] [rendered]
chunk {1} main-es2015.a8d7ba2f3acff1277bcc.js (main) 652 kB [initial] [rendered]
chunk {1} main-es5.a8d7ba2f3acff1277bcc.js (main) 768 kB [initial] [rendered]
我刚刚尝试了一种似乎可行的方法:
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*
使缩小后的构建文件搜索变得容易。