web-dev-qa-db-ja.com

本番ビルドで環境変数にアクセスするAngular 4

ユーザーがテストできるように構成可能なAPIURLを使用してangularアプリの本番ビルドをデプロイしたい。environment.tsを使用しているが、本番ビルド後、その方法がわからない変数を構成します。

どのようなアプローチを行う必要がありますか?

5
OreoFanatics

Angular-CLIを使用していますか?それなら、それは簡単なはずです。あなたはこのようなものを持っています:

src/
  app/
  environment/
    environment.ts
    environment.prod.ts

environment.prod.tsに別のURLを入力するだけで、製品ビルドは2番目のURLを取得します。例えば。 environment.tsが次のようになっているとしましょう。

{
  "production": false,
  "apiUrl": "http://localhost:8080"
}

これをenvironment.prod.tsに入れてください:

{
  "production": true,
  "apiUrl": "https://example.com/api"
}

より多くの環境をセットアップできます。.angular-cli.jsonのそのセクションとangular-cliリポジトリを確認してください。

編集:あなたのコメントによると、あなたはもっと欲しいです。

はい、それでもビルド後は設定できませんね。ユーザーが使用するURLがわからないため、ビルドをデプロイした後、外部から構成できるようにします。

このシナリオをさらに続けましょう。バックエンドクライアントを作成しましょう。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { apiUrl } from '../environment/environment.ts';
@Injectable()
export class BackendService {
    backendUrl: string = apiUrl;      

    constructor(private httpClient: HttpClient) {}

    get(endpoint: string, params: any): Observable<any> {
      const url= `${this.backendUrl}/${endpoint}`;
      return this.httpClient.get(url, params);
    }
}

簡略化されていますが、機能します。デフォルトでは、独自のURLを設定します。ただし、コンポーネントはその場でURLを設定し、そのURLから他のものを取得できます。

さて、次のステップは、あなたが持っているバックエンドを提供することです。これは事前構成された配列にすることも、クライアントにURLを自由に入力させることもできます(単に入力ボックス)。これを行うコンポーネントを作成し、ここでこのサービスを構成できます。おそらく、「適切な」バックエンド用に別のサービスを用意する必要があります。あなたの認証は嘘です。しかし、これはすべて実際にはシナリオによって異なります。

6
Zlatko

Environment * .tsファイルにはビルド時の構成が含まれており、ビルド後に変更することはできません。ビルド後に構成を変更する必要がある場合は、それらを別の場所に配置し、アプリケーションの起動時に動的に取得する必要があります

あなたができることは:

ステップ#1:json構成ファイルをsrc/assets/config/[envName] .jsonの下に置きます。

注:ts形式ではなくjson形式である必要があります

ステップ#2:新しい構成サービスを追加します

import {Inject, Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {Observable} from 'rxjs/Rx';
import {environment} from "../../environments/environment";

/**
 * Declaration of config class
 */
export class AppConfig
{
//Your properties here
  readonly production: boolean;
  readonly name: string;

  readonly apiBaseUrl: string;

}

/**
 * Global variable containing actual config to use. Initialised via ajax call
 */
export let APP_CONFIG: AppConfig;

/**
 * Service in charge of dynamically initialising configuration
 */
@Injectable()
export class AppConfigService
{

  constructor(private http: HttpClient)
  {
  }

  public load()
  {
    return new Promise((resolve, reject) => {

      let confName = environment.name + '.json';
      this.http.get('/assets/config/' + confName).map(res => res as any).catch((error: any): any => {
        reject(true);
        return Observable.throw('Server error');
      }).subscribe((envResponse :any) => {
        let t = new AppConfig();
        //Modify envResponse here if needed (e.g. to ajust parameters for https,...)
        APP_CONFIG = Object.assign(t, envResponse);
        resolve(true);
      });

    });
  }
}

ステップ#:メインモジュールで、モジュールを宣言する前にこれを追加します

/**
* Exported function so that it works with AOT
* @param {AppConfigService} configService
* @returns {Function}
*/
export function loadConfigService(configService: AppConfigService): Function 

{
  return () => { return configService.load() }; 
}

ステップ#4:モジュールプロバイダーを変更して、このプロバイダーを追加します:[…

  AppConfigService,
  { provide: APP_INITIALIZER, useFactory: loadConfigService , deps: [AppConfigService], multi: true },


],

ステップ5:コードでは、environment.configXXXを使用する代わりに、これを使用します

import {APP_CONFIG} from "../services/app-config.service";

//…
return APP_CONFIG.configXXX;

これは単純化された例です。http呼び出しを行うときに絶対URLが必要なため、angular Universal)を使用する場合は、実際にいくつかの変更を加える必要があります。

10
David
  • 構成をアセットフォルダーのtsファイルに入れます
  • environment.tsをフェッチするのと同じように、そのファイルをフェッチしてその構成を使用します
  • アセットフォルダーの内容は最小化されていないため、本番ビルドでも構成できます
4