【问题标题】:How to load runtime configuration and use it in an angular module?如何加载运行时配置并在角度模块中使用它?
【发布时间】:2021-02-26 11:00:29
【问题描述】:

关注Apollo Angular setup

src/app/graphql.module.ts

import { NgModule } from '@angular/core';
import { APOLLO_OPTIONS } from 'apollo-angular';
import { ApolloClientOptions, InMemoryCache, createHttpLink } from '@apollo/client/core';
import { HttpLink } from 'apollo-angular/http';

const uri = 'http://localhost:3000/graphql'; // <-- add the URL of the GraphQL server here
export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
  return {
    link: httpLink.create({ uri }),
    cache: new InMemoryCache(),
  };
}

@NgModule({
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink],
    },
  ],
})
export class GraphQLModule {}

这为我们提供了一个硬编码的 URI 变量,它显然不能在本地开发之外工作。我希望能够通过在运行时加载配置文件来更改 URI,而不是构建时间(即不使用 environment.ts)。看了Runtime environment configuration with Angular,觉得这个方法比较合理。

assets/config.json

将在部署时覆盖的本地开发的默认配置

{
  "apiUrl": "http://localhost:3000/graphql"
}

src/app/app-config.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

interface AppConfig {
  apiUri: string;
}

@Injectable({
  providedIn: 'root'
})
export class AppConfigService {
  private appConfig: AppConfig;
  private http: HttpClient;

  constructor(http: HttpClient) {
    this.http = http;
  }

  async loadAppConfig() {
    this.appConfig = await this.http.get('/assets/config.json')
      .toPromise() as AppConfig;
  }

  public get apiUri() {
    return this.appConfig.apiUri;
  }
}

src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { GraphQLModule } from './graphql.module';
import { AppConfigService } from './app-config.service';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule, GraphQLModule, HttpClientModule],
  providers: [
    {
      provide : APP_INITIALIZER,
      multi : true,
      deps : [AppConfigService],
      useFactory : (appConfigService : AppConfigService) =>  () => appConfigService.loadAppConfig()
    }
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

所以我的问题是,如何使用GraphQLModule 中的AppConfigService 来获取apiUrl 并将其设置为createApollo 工厂函数中的uri

【问题讨论】:

  • 你好兄弟!你解决了吗?

标签: angular apollo apollo-angular


【解决方案1】:
import {NgModule} from '@angular/core';
import {APOLLO_OPTIONS} from 'apollo-angular';
import {ApolloClientOptions, InMemoryCache} from '@apollo/client/core';
import {HttpLink} from 'apollo-angular/http';
import {ConfigService} from './config.service';

export function createApollo(
  httpLink: HttpLink,
  configService: ConfigService
): ApolloClientOptions<any> {
  return {
    link: httpLink.create({uri: configService.apiUri}),
    cache: new InMemoryCache(),
  };
}

@NgModule({
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink, ConfigService],
    },
  ],
})
export class GraphQLModule {}

【讨论】:

    【解决方案2】:

    APP_INITIALIZER 令牌在您的应用程序启动时调用,这是设置 apollo 客户端的最佳位置,但尽管官方 apollo-angular documentation 建议使用 APOLLO_OPTIONS 令牌,但如果您需要以异步方式设置客户端我建议在你的 promise 的 map 函数中使用 apollo.create 方法:

    src/app/app.module.ts

    @NgModule({
      ...
      providers: [
        {
          provide: APP_INITIALIZER,
          useFactory: (appConfigService: AppConfigService, apollo: Apollo, httpLink: HttpLink) =>
            () => appConfigService.loadAppConfig()
              .pipe(
                map((appConfig: AppConfig) => {
                  apollo.create({
                    link: httpLink.create({
                      uri: appConfig.apiUrl,
                    }),
                    cache: new InMemoryCache(),
                  });
                })
              ).toPromise(),
          deps: [AppConfigService, Apollo, HttpLink],
          multi: true
        },
      ],
      ...
    })
    export class AppModule {
    }
    

    【讨论】:

      【解决方案3】:

      您是否尝试过使用代理?这将允许您在运行应用程序之前设置要指向的主机。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-25
        • 1970-01-01
        • 2011-01-18
        • 2011-02-20
        • 1970-01-01
        相关资源
        最近更新 更多