如何在Apollo-Angular中管理多个GraphQL模块避免配置冲突
问题根因
该现象由Angular依赖注入的默认行为导致:同一个注入令牌APOLLO_NAMED_OPTIONS在多个模块中声明Provider时,默认执行后声明的配置覆盖先声明的配置逻辑,因此只有最后导入的GraphQL模块的配置会被Apollo识别,其余配置全部丢失。
解决方案
方案1:统一合并配置(适配所有场景)
无论是否可修改子模块代码,都可以在应用根模块中统一声明合并后的APOLLO_NAMED_OPTIONS,将所有需要用到的命名配置汇总到同一个Provider中,示例如下:
import { NgModule } from '@angular/core'; import { APOLLO_NAMED_OPTIONS, NamedOptions } from 'apollo-angular'; import { InMemoryCache } from '@apollo/client/core'; import { HttpLink } from 'apollo-angular/http'; import { AppListGraphQLModule } from './applist-gql.module'; import { GameGraphQLModule } from './game-gql.module'; @NgModule({ imports: [ // 导入所有第三方/内部GraphQL模块 AppListGraphQLModule, GameGraphQLModule ], providers: [ { provide: APOLLO_NAMED_OPTIONS, useFactory(httpLink: HttpLink): NamedOptions { return { // 合并所有需要的命名配置 appList: { cache: new InMemoryCache(), link: httpLink.create({ uri: 'https://graphql-voter-app.herokuapp.com/', }), defaultOptions: { query: { fetchPolicy: 'no-cache', }, watchQuery: { fetchPolicy: 'no-cache', }, }, }, switchFauna: { cache: new InMemoryCache(), link: httpLink.create({ uri: 'https://graphql-voter-app.herokuapp.com/', }), defaultOptions: { query: { fetchPolicy: 'no-cache', }, watchQuery: { fetchPolicy: 'no-cache', }, }, } }; }, deps: [HttpLink], }, ] }) export class AppModule {}
方案2:子模块加multi标记(适合内部模块/可修改的公共库场景)
如果所有提供GraphQL配置的模块都支持修改,可以给每个模块的APOLLO_NAMED_OPTIONS Provider添加multi: true标记,允许同令牌注入多组配置,之后在根模块中做自动合并:
- 修改每个GraphQL子模块的Provider配置:
// 以AppListGraphQLModule为例,GameGraphQLModule做相同修改 @NgModule({ providers: [ { provide: APOLLO_NAMED_OPTIONS, useFactory(httpLink: HttpLink): NamedOptions { // 原有逻辑不变 return { appList: { /* 原有配置 */ } }; }, deps: [HttpLink], multi: true // 新增这一行 }, ], }) export class AppListGraphQLModule {}
- 在根模块新增自动合并逻辑:
import { NgModule, InjectionToken } from '@angular/core'; import { APOLLO_NAMED_OPTIONS, NamedOptions } from 'apollo-angular'; function mergeApolloOptions(optionsList: NamedOptions[]): NamedOptions { return optionsList.reduce((merged, current) => Object.assign(merged, current), {}); } @NgModule({ imports: [ /* 所有GraphQL子模块 */ ], providers: [ { provide: APOLLO_NAMED_OPTIONS, useFactory: mergeApolloOptions, deps: [APOLLO_NAMED_OPTIONS as InjectionToken<NamedOptions[]>] } ] }) export class AppModule {}
内容的提问来源于stack exchange,提问作者smkarber
相关产品推荐
相关产品推荐

