【问题标题】:How to make Angular mock service tree-shakeable如何使 Angular 模拟服务可摇树
【发布时间】:2020-06-19 02:07:39
【问题描述】:

上下文

在 Angular 9 项目中,我使用两种环境:productionmock

在核心模块中,我检查模拟环境。

  • 如果使用模拟配置进行构建,我会注入返回模拟数据的模拟服务,因此不会发出外部 http 请求。

  • 如果使用 prod 配置进行构建,则注入真正的服务。

我是这样做的:

 core.module.ts

@NgModule({
  declarations: [],
  providers: [],
  imports: [BrowserModule, HttpClientModule],
  exports: [],
})
export class CoreModule {}

country.service.proxy.ts

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[]>;
}

其中ServiceMockService 实现相同的接口。

这行得通。

问题

代码不是可摇树。结果是在我的包中(当我运行ng build --prod 时)甚至包括模拟服务。

我想在开发过程中将每个服务从 mock 切换到 prod。

目标

如何让 Angular 只捆绑将要使用的服务?


我正在使用:

Angular CLI: 9.0.4
Node: 13.6.0
OS: darwin x64

Ivy Workspace: Yes

谢谢! :)

【问题讨论】:

  • 您是否尝试过在您的environment.ts 文件中设置不同的版本?我实际上不知道这是否可行 - 只是一个建议!
  • @KurtHamilton 版本是什么?我的环境有键:mockproduction

标签: angular typescript service bundle tree-shaking


【解决方案1】:

我刚刚尝试了一种似乎可行的方法:

  • 在您的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());
}

当我检查我的构建文件时,我只在 dev 构建中找到 qwertydev,在 prod 构建中找到 qwertprod,这表明它们已经过 tree-shaken。

我使用字符串qwerty* 方便在缩小后搜索构建文件。

在模块中声明服务

我已经在模块中声明了提供者以避免循环引用。通过将服务声明为providedIn: Module,很容易引入循环引用。

您可以通过声明第三方模块来解决此问题,但这似乎有点过头了。

我已经在较早的答案中证明了这一点:@Injectable() decorator and providers array

替代方法

在环境文件中声明服务工厂感觉不太相当。我这样做只是为了简单起见。您可以创建自己的一组特定于环境的文件,这些文件在构建时以与环境文件相同的方式被覆盖,但坦率地说,这听起来像是一场维护噩梦。

【讨论】:

  • 谢谢!它工作:) 模拟服务没有出现在捆绑包中。正在发生的一件奇怪的事情是,尽管这些文件不包括在内,但捆绑包的大小是相同的。你知道为什么吗?
  • 很奇怪。我最近在捆绑大小方面得到了一些意想不到的结果。尽管我还没有真正进行大量调查,但我还没有意识到任何明显的原因。
猜你喜欢
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
  • 2019-09-21
  • 1970-01-01
  • 1970-01-01
  • 2020-10-18
  • 2019-05-08
  • 2020-12-10
相关资源
最近更新 更多