prosource

App.settings - Angular way?

probook 2023. 5. 28. 20:53
반응형

App.settings - Angular way?

는 고싶다습니하를 .App Settings일부 제약 조건과 미리 정의된 값을 포함하는 내 앱으로 이동합니다.

나는 이미 이 읽었습니다. 이 대답은 다음과 같습니다.OpaqueToken그러나 Angular에서는 더 이상 사용되지 않습니다.기사는 차이점을 설명하지만 완전한 예를 제공하지 못했고, 저의 시도는 실패했습니다.

제가 시도한 것은 다음과 같습니다(이것이 올바른 방법인지 모르겠습니다).

//ServiceAppSettings.ts

import {InjectionToken, OpaqueToken} from "@angular/core";

const CONFIG = {
  apiUrl: 'http://my.api.com',
  theme: 'suicid-squad',
  title: 'My awesome app'
};
const FEATURE_ENABLED = true;
const API_URL = new InjectionToken<string>('apiUrl');

다음은 이러한 제약 조건을 사용할 구성 요소입니다.

//MainPage.ts

import {...} from '@angular/core'
import {ServiceTest} from "./ServiceTest"

@Component({
  selector: 'my-app',
  template: `
   <span>Hi</span>
  ` ,  providers: [
    {
      provide: ServiceTest,
      useFactory: ( apiUrl) => {
        // create data service
      },
      deps: [

        new Inject(API_URL)
      ]
    }
  ]
})
export class MainPage {


}

하지만 작동하지 않고 오류가 발생합니다.

질문:.

어떻게 "앱"을 소비할 수 있습니까?settings"는 Angular way 값을 참조하십시오.

덜커덕터

NB 주입식 서비스를 생성하여 NgModule 공급자에 넣을 수 있지만, 앞서 말했듯이 저는 그것을 하고 싶습니다.InjectionToken앵글족의 길

다음을 사용하는 것은 권장되지 않습니다.environment.*.tsAPI URL 구성을 위한 파일입니다.이것이 "환경"이라는 단어를 언급하고 있기 때문에 그렇게 해야 할 것 같습니다.

이를 사용하는 것은 실제로 컴파일 시간 구성입니다.API URL을 변경하려면 다시 빌드해야 합니다.그건 당신이 하고 싶지 않은 일입니다...그냥 친절한 QA 부서에 물어보세요 :)

필요한 것은 런타임 구성, 즉 앱이 시작될 때 구성을 로드하는 것입니다.

일부 다른 답변은 이에 대해 언급하지만, 이 시작되는 즉시 구성을 로드해야 일반 서비스에서 필요할 때마다 사용할 수 있다는 점이 다릅니다.

런타임 구성을 구현하는 방법

  1. 을 JSON 파일에 합니다./src/assets/folder (되도록) (파일 이름: folder
  2. 다음을 작성합니다.AppConfigService하고 배포합니다.
  3. APP_INITIALIZER

을 에 합니다./src/assets

폴더에 즉, Angular CLI를 을 알 수 있습니다.angular.json폴더를 하십시오.자산 폴더를 사용하여 시작합니다.

{
  "apiBaseUrl": "https://development.local/apiUrl"
}

만들기AppConfigService

구성 값이 필요할 때마다 주입되는 서비스입니다.

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

@Injectable({
  providedIn: 'root'
})
export class AppConfigService {

  private appConfig: any;

  constructor(private http: HttpClient) { }

  loadAppConfig() {
    return this.http.get('/assets/config.json')
      .toPromise()
      .then(data => {
        this.appConfig = data;
      });
  }

  // This is an example property ... you can make it however you want.
  get apiBaseUrl() {

    if (!this.appConfig) {
      throw Error('Config file not loaded!');
    }

    return this.appConfig.apiBaseUrl;
  }
}

APP_INITIALIZER

허하기용을 AppConfigService안전하게 주입하려면 구성이 완전히 로드된 상태에서 앱 시작 시 구성을 로드해야 합니다.중요한가 중한것초공기장다음반을것한입다니다는야환해를 해야 한다는 것입니다.PromiseAngular가 시작을 완료하기 전에 해결이 완료될 때까지 대기하도록 합니다.

import { APP_INITIALIZER } from '@angular/core';
import { AppConfigService } from './services/app-config.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      multi: true,
      deps: [AppConfigService],
      useFactory: (appConfigService: AppConfigService) => {
        return () => {
          //Make sure to return a promise!
          return appConfigService.loadAppConfig();
        };
      }
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

이제 필요한 곳이면 어디든 주입할 수 있으므로 모든 구성을 읽을 수 있습니다.

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {

  apiBaseUrl: string;

  constructor(private appConfigService: AppConfigService) {}

  ngOnInit(): void {
    this.apiBaseUrl = this.appConfigService.apiBaseUrl;
  }

}

API URL을 컴파일 시간 구성으로 구성하는 것은 안티패턴이라고 할 수 없습니다.런타임 구성을 사용합니다.

를 사용하는 경우 다음과 같은 다른 옵션이 있습니다.

는 Angular CLI에서 환경 합니다.src/environments은 (으)입니다.environment.ts및 (dev) »environment.prod.ts(생산).

성매변 .environment.* 파일:

environment.ts:

export const environment = {
  production: false,
  apiEndpoint: 'http://localhost:8000/api/v1'
};

environment.sys.ts:

export const environment = {
  production: true,
  apiEndpoint: '__your_production_server__'
};

올바른 환경 파일이 자동으로 선택됩니다.

api.service.ts

// ... other imports
import { environment } from '../../environments/environment';

@Injectable()
export class ApiService {     

  public apiRequest(): Observable<MyObject[]> {
    const path = environment.apiEndpoint + `/objects`;
    // ...
  }

// ...
}

Github(Angular CLI 버전 6) 또는 공식 Angular 가이드(버전 7)에서 애플리케이션 환경에 대해 자세히 알아보십시오.

주사로 이걸 어떻게 하는지 알아냈어요토큰(아래 예 참조) 및 프로젝트가 Angular CLI를 사용하여 작성된 경우 에 있는 환경 파일을 사용할 수 있습니다./environments끝점과 정적 환경 은 객체 리터럴에 두하게 될 가능성이 . API를 사용한 한 구성의 경우 API를 사용합니다.InjectionToken할 수 에 초기 데이터, 프로그램의 으로 환경 할 수

주입 토큰 예제

/app/app-config.sys.ts

import { NgModule, InjectionToken } from '@angular/core';
import { environment } from '../environments/environment';

export let APP_CONFIG = new InjectionToken<AppConfig>('app.config');

export class AppConfig {
  apiEndpoint: string;
}

export const APP_DI_CONFIG: AppConfig = {
  apiEndpoint: environment.apiEndpoint
};

@NgModule({
  providers: [{
    provide: APP_CONFIG,
    useValue: APP_DI_CONFIG
  }]
})
export class AppConfigModule { }

/app/app.sys.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppConfigModule } from './app-config.module';

@NgModule({
  declarations: [
    // ...
  ],
  imports: [
    // ...
    AppConfigModule
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

이제 다음과 같은 모든 구성 요소, 서비스 등으로 디아이디할 수 있습니다.

/app/core/auth.service.ts

import { Injectable, Inject } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

import { APP_CONFIG, AppConfig } from '../app-config.module';
import { AuthHttp } from 'angular2-jwt';

@Injectable()
export class AuthService {

  constructor(
    private http: Http,
    private router: Router,
    private authHttp: AuthHttp,
    @Inject(APP_CONFIG) private config: AppConfig
  ) { }

  /**
   * Logs a user into the application.
   * @param payload
   */
  public login(payload: { username: string, password: string }) {
    return this.http
      .post(`${this.config.apiEndpoint}/login`, payload)
      .map((response: Response) => {
        const token = response.json().token;
        sessionStorage.setItem('token', token); // TODO: can this be done else where? interceptor
        return this.handleResponse(response); // TODO:  unset token shouldn't return the token to login
      })
      .catch(this.handleError);
  }
   
  // ...
}

그런 다음 내보낸 AppConfig를 사용하여 구성 확인을 입력할 수도 있습니다.

는 사을용습다니를 했습니다.APP_INITIALIZER다른 서비스 공급자가 구성을 주입해야 하는 상황에서는 작동하지 않기 때문입니다.이전에 인스턴스화할 수 있습니다.APP_INITIALIZER실행됩니다.

사하는다솔보다았니습을루션른용▁that▁▁use다니보▁i았습▁other를 사용하는 다른 솔루션들을 본 적이 있습니다.fetch config.json 파일에 대한 변수의 합니다.platformBrowserDynamic()루트 모듈을 부트스트랩하기 전에.그렇지만fetch일부 브라우저와 특히 대상 모바일 장치의 WebView 브라우저에서 지원되지 않습니다.

다음은 PWA와 모바일 장치(WebView) 모두에서 사용할 수 있는 솔루션입니다.참고: 지금까지 Android에서만 테스트했습니다. 집에서 일하는 것은 Mac에서 빌드할 수 없다는 것을 의미합니다.

main.ts:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { APP_CONFIG } from './app/lib/angular/injection-tokens';

function configListener() {
  try {
    const configuration = JSON.parse(this.responseText);

    // pass config to bootstrap process using an injection token
    platformBrowserDynamic([
      { provide: APP_CONFIG, useValue: configuration }
    ])
      .bootstrapModule(AppModule)
      .catch(err => console.error(err));

  } catch (error) {
    console.error(error);
  }
}

function configFailed(evt) {
  console.error('Error: retrieving config.json');
}

if (environment.production) {
  enableProdMode();
}

const request = new XMLHttpRequest();
request.addEventListener('load', configListener);
request.addEventListener('error', configFailed);
request.open('GET', './assets/config/config.json');
request.send();

다음 코드:

  1. ▁for다에 대한 비동기 합니다.config.json 파일파.
  2. 요청이 완료되면 JSON을 Javascript 개체로 구문 분석합니다.
  3. 는 를사여값제니다공을 을 제공합니다.APP_CONFIG부트스트래핑 이전의 주입 토큰입니다.
  4. 마지막으로 루트 모듈을 부트스트랩합니다.

APP_CONFIG 그면 의추제주수있입다니습될게의 추가 될 수 .app-module.ts그리고 그것은 정의될 것입니다.를 들어, 를예들어초수할있다습니화기을다음ise▁the다있▁for니▁initial▁can수습▁i▁example를 초기화할 수 있습니다.FIREBASE_OPTIONS 주입 @angular/fire다음을 포함합니다.

{
      provide: FIREBASE_OPTIONS,
      useFactory: (config: IConfig) => config.firebaseConfig,
      deps: [APP_CONFIG]
}

저는 이 모든 것이 매우 일반적인 요구 사항에 대해 놀랍도록 어려운(그리고 진부한) 일이라고 생각합니다.가까운 미래에 비동기 공급자 공장에 대한 지원과 같은 더 나은 방법이 있기를 바랍니다.

나머지 코드는 완전성을 위해...

app/lib/angular/injection-tokens.ts:

import { InjectionToken } from '@angular/core';
import { IConfig } from '../config/config';

export const APP_CONFIG = new InjectionToken<IConfig>('app-config');

그고리로.app/lib/config/config.tsJSON 구성 파일의 인터페이스를 정의합니다.

export interface IConfig {
    name: string;
    version: string;
    instance: string;
    firebaseConfig: {
        apiKey: string;
        // etc
    }
}

은 구저위에 됩니다.assets/config/config.json:

{
  "name": "my-app",
  "version": "#{Build.BuildNumber}#",
  "instance": "localdev",
  "firebaseConfig": {
    "apiKey": "abcd"
    ...
  }
}

참고: Azure DevOps 태스크를 사용하여 빌드를 삽입합니다.빌드 번호를 지정하고 배포 중인 다른 배포 환경에 대한 다른 설정으로 대체합니다.

Poorman의 구성 파일:

본문 태그의 첫 번째 줄로 index.html에 추가합니다.

<script lang="javascript" src="assets/config.js"></script>

자산/config.js 추가:

var config = {
    apiBaseUrl: "http://localhost:8080"
}

config.ts 추가:

export const config: AppConfig = window['config']

export interface AppConfig {
    apiBaseUrl: string
}

다음은 .json의 로드를 통해 재구성 없이 변경할 수 있는 솔루션입니다.

import { Injectable, Inject } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Location } from '@angular/common';

@Injectable()
export class ConfigService {

    private config: any;

    constructor(private location: Location, private http: Http) {
    }

    async apiUrl(): Promise<string> {
        let conf = await this.getConfig();
        return Promise.resolve(conf.apiUrl);
    }

    private async getConfig(): Promise<any> {
        if (!this.config) {
            this.config = (await this.http.get(this.location.prepareExternalUrl('/assets/config.json')).toPromise()).json();
        }
        return Promise.resolve(this.config);
    }
}

및 config.json

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

Angular 구성 가 꽤 .AppConfigService 이와 같은.

하지만 저는 가끔 이것이 효과가 없다는 것을 알았습니다.

"config.json" 파일을 가지고 있는 것이 더 간단하고 신뢰할 수 있으며, 이를 읽은 후 값을 반환하는 클래스를 만드는 것이 더 쉬웠습니다. 예를 들어, 내 구성 파일은 다음과 같습니다.

{
  "appName": "Mike's app",
  "version": "1.23.4",
  "logging_URL" : "https://someWebsite.azurewebsites.net/logs"
}

다음을 사용하여 값에 액세스할 수 있습니다.

import config from '../../assets/config.json';

@Injectable({
    providedIn: 'root'
})
export class AppConfigService {
    get appName() {
        return config.appName; 
    }
    get appVersion() {
        return config.version; 
    }
    get loggingUrl() {
        return config.logging_URL; 
    }
}

(몇 달 후...)

더 간단한 Angular 솔루션을 만든 것에 대해 스스로를 칭찬한 후, 저는 이것이 큰 단점이 있다는 것을 깨달았습니다.AppConfig Service를 사용하고 CI/CD를 사용하는 경우 빌드 프로세스를 통해 config.json 파일을 업데이트할 수 있으며 Angular 앱은 이러한 설정을 사용합니다.

내 버전에서는 더 간단하지만 덮어쓸 구성 설정 파일이 없습니다.자동화된 빌드 프로세스의 경우 이는 바람직하지 않을 수 있습니다.

이에 대한 두 가지 해결책이 있습니다.

json 파일에 저장

json 파일을 만들고 다음으로 당신의 구성 요소에 들어가세요.$http.get()ㅠㅠ. 내가 내가 이것을 아주 낮게 필요로 했다면 그것은 좋고 빠릅니다.

데이터 서비스를 사용하여 저장

모든 구성 요소를 저장하고 사용하거나 사용량이 많은 경우에는 데이터 서비스를 사용하는 것이 좋습니다.다음과 같이:

  1. 내에정적폴만하됩니다면들만 안에 정적 만 하면 .src/app폴더를 누릅니다.

  2. 이름이 다음인 파일을 만듭니다.fuels.ts정적 폴더로 이동합니다.다른 정적 파일도 여기에 저장할 수 있습니다.데이터를 다음과 같이 정의합니다.연료 데이터를 보유하고 있다고 가정합니다.

__

export const Fuels {

   Fuel: [
    { "id": 1, "type": "A" },
    { "id": 2, "type": "B" },
    { "id": 3, "type": "C" },
    { "id": 4, "type": "D" },
   ];
   }
  1. 정적 파일 이름을 만듭니다.services.ts

__

import { Injectable } from "@angular/core";
import { Fuels } from "./static/fuels";

@Injectable()
export class StaticService {

  constructor() { }

  getFuelData(): Fuels[] {
    return Fuels;
  }
 }`
  1. 이제 모든 모듈에 대해 이 기능을 사용할 수 있습니다.

이와 같이 app.vmx.ts 파일로 가져오기만 하면 공급자가 변경됩니다.

import { StaticService } from './static.services';

providers: [StaticService]

이제 이것을 다음으로 사용합니다.StaticService모든 모듈에서.

이상입니다.

제가 가입하고 사용자 및 환경 정보에 로컬 스토리지를 사용하는 솔루션을 구축하기 전에 이러한 문제가 있었습니다.정확하게는 각 1.0일입니다.이전에는 런타임에 생성된 apiurl을 글로벌 변수에 배치하는 js 파일을 동적으로 만들고 있었습니다.우리는 요즘 OOP를 조금 더 많이 사용하고 있으며, 로컬 스토리지를 어떤 용도로도 사용하지 않습니다.

저는 환경 결정과 apiurl 생성 모두를 위한 더 나은 솔루션을 만들었습니다.

이것은 어떻게 다른가요?

config.json 파일이 로드되지 않으면 앱이 로드되지 않습니다.공장 기능을 사용하여 더 높은 수준의 SOC를 생성합니다.이를 서비스로 캡슐화할 수는 있지만 파일의 여러 섹션이 파일 내에 함께 존재한다는 것이 유일한 공통점일 때는 전혀 이유를 찾을 수 없었습니다.공장 기능을 사용하면 기능을 모듈에 직접 전달할 수 있습니다. 기능을 직접 전달할 수 있습니다.마지막으로, 저는 주입을 설정하는 것이 더 쉽습니다.공장 기능을 사용할 수 있는 경우 토큰입니다.

단점은?

구성하려는 모듈이 Root() 또는 Child()에 대해 공장 기능을 전달할 수 없고 공장 기능을 사용하여 패키지를 구성할 다른 방법이 없는 경우 이 설정(및 대부분의 다른 응답)을 사용하면 운이 좋지 않습니다.

지침들

  1. 가져오기를 사용하여 json 파일을 검색하여 개체를 창에 저장하고 사용자 지정 이벤트를 발생시킵니다. - IE 호환성을 위해 what wg-fetch를 설치하고 polyfiles.ts에 추가해야 합니다.
  2. 사용자 지정 이벤트를 수신하는 이벤트 수신기를 지정합니다.
  3. 이벤트 수신기는 이벤트를 수신하고 창에서 관찰 가능한 창으로 개체를 검색한 다음 창에 저장된 내용을 지웁니다.
  4. 부트스트랩 각도

이것이 제 해결책이 정말로 달라지기 시작하는 부분입니다.

  1. . -- 이 되고 .json을 지정하지 json 파일 - 파일 이름을 지정할 수 .{}또는any 더 할 수 것을 때.
  2. 3단계에서 구문 분석된 json 파일을 전달할 BehaviorSubject를 만듭니다.
  3. SOC를 유지하기 위해 공장 기능을 사용하여 구성의 다른 섹션을 참조합니다.
  4. 주입 작성공장 기능의 결과를 필요로 하는 공급자를 위한 토큰

및/또는 --

  1. Root() 메서드 또는 Child() 메서드에서 함수를 수신할 수 있는 모듈에 공장 함수를 직접 전달합니다.

메인.ts

main.ts의 코드가 실행되기 전에 창["환경"]이 다른 방법으로 채워지는 솔루션을 허용하기 위해 이벤트 수신기를 만들기 전에 창["환경"]이 채워지지 않음을 확인합니다.

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { configurationSubject } from './app/utils/environment-resolver';

var configurationLoadedEvent = document.createEvent('Event');
configurationLoadedEvent.initEvent('config-set', true, true);
fetch("../../assets/config.json")
.then(result => { return result.json(); })
.then(data => {
  window["environment"] = data;
  document.dispatchEvent(configurationLoadedEvent);
}, error => window.location.reload());

/*
  angular-cli only loads the first thing it finds it needs a dependency under /app in main.ts when under local scope. 
  Make AppModule the first dependency it needs and the rest are done for ya. Event listeners are 
  ran at a higher level of scope bypassing the behavior of not loading AppModule when the 
  configurationSubject is referenced before calling platformBrowserDynamic().bootstrapModule(AppModule)

  example: this will not work because configurationSubject is the first dependency the compiler realizes that lives under 
  app and will ONLY load that dependency, making AppModule an empty object.

  if(window["environment"])
  {
    if (window["environment"].production) {
      enableProdMode();
    }
    configurationSubject.next(window["environment"]);
    platformBrowserDynamic().bootstrapModule(AppModule)
    .catch(err => console.log(err));
  }
*/
if(!window["environment"]) {
  document.addEventListener('config-set', function(e){
    if (window["environment"].production) {
      enableProdMode();
    }
    configurationSubject.next(window["environment"]);
    window["environment"] = undefined;
    platformBrowserDynamic().bootstrapModule(AppModule)
    .catch(err => console.log(err));
  });
}

환경 보호에 관한 지식

중복성을 위해 창["환경"]을 사용하여 BehaviorSubject에 값을 할당합니다.main.ts의 코드를 포함하여 Angular의 앱 코드가 실행될 때까지 구성이 이미 사전 로드되고 창["환경"]이 이미 채워지는 솔루션을 고안할 수 있습니다.

import { BehaviorSubject } from "rxjs";
import { IConfig } from "../config.interface";

const config = <IConfig>Object.assign({}, window["environment"]);
export const configurationSubject = new BehaviorSubject<IConfig>(config);
export function resolveEnvironment() {
  const env = configurationSubject.getValue().environment;
  let resolvedEnvironment = "";
  switch (env) {
 // case statements for determining whether this is dev, test, stage, or prod
  }
  return resolvedEnvironment;
}

export function resolveNgxLoggerConfig() {
  return configurationSubject.getValue().logging;
}

app.module.ts - 이해하기 쉽게 분해됨

재미있는 사실!이전 버전의 NGXLogger에서는 개체를 LoggerModule.forRoot()에 전달해야 했습니다.사실, 로거 모듈은 여전히 작동합니다!NGXLogger는 설정에 공장 기능을 사용할 수 있도록 재정의할 수 있는 LoggerConfig를 제공합니다.

import { resolveEnvironment, resolveNgxLoggerConfig, resolveSomethingElse } from './environment-resolvers';
import { LoggerConfig } from 'ngx-logger';
@NgModule({
    modules: [
        SomeModule.forRoot(resolveSomethingElse)
    ],
    providers:[
        {
            provide: ENVIRONMENT,
            useFactory: resolveEnvironment
        },
        { 
            provide: LoggerConfig,
            useFactory: resolveNgxLoggerConfig
        }
    ]
})
export class AppModule

부록

API URL 생성을 어떻게 해결했습니까?

자바스크립트(IMO) 대비 TypeScript의 가장 큰 강점이기 때문에 각 URL이 무엇을 하는지 댓글로 이해하고 유형 확인을 원했습니다.저는 또한 다른 개발자들이 새로운 엔드포인트를 추가할 수 있는 경험을 만들고 싶었고, 가능한 한 완벽한 아피스를 만들고 싶었습니다.

환경(dev, test, stage, prod, "" 등)을 받아들이는 클래스를 만들고 이 값을 각 API 컬렉션의 기본 URL을 만드는 작업을 하는 일련의 클래스[1-N]에 전달했습니다.각 API Collection은 각 API 컬렉션에 대한 기본 URL을 생성하는 역할을 합니다.자체 API, 공급업체의 API 또는 외부 링크일 수 있습니다.해당 클래스는 생성된 기본 URL을 포함하는 각 후속 api로 전달합니다.아래의 코드를 읽고 맨본 예제를 확인하십시오.일단 설정되면 다른 개발자가 다른 것을 건드리지 않고도 다른 엔드포인트를 API 클래스에 추가하는 것이 매우 간단합니다.

TLDR; 메모리 최적화를 위한 기본 OOP 원칙 및 레이지 게터

@Injectable({
    providedIn: 'root'
})
export class ApiConfig {
    public apis: Apis;

    constructor(@Inject(ENVIRONMENT) private environment: string) {
        this.apis = new Apis(environment);
    }
}

export class Apis {
    readonly microservices: MicroserviceApiCollection;

    constructor(environment: string) {
        this.microservices = new MicroserviceApiCollection(environment);
    }
}

export abstract class ApiCollection {
  protected domain: any;

  constructor(environment: string) {
      const domain = this.resolveDomain(environment);
      Object.defineProperty(ApiCollection.prototype, 'domain', {
          get() {
              Object.defineProperty(this, 'domain', { value: domain });
              return this.domain;
          },
          configurable: true
      });
  }
}

export class MicroserviceApiCollection extends ApiCollection {
  public member: MemberApi;

  constructor(environment) {
      super(environment);
      this.member = new MemberApi(this.domain);
  }

  resolveDomain(environment: string): string {
      return `https://subdomain${environment}.actualdomain.com/`;
  }
}

export class Api {
  readonly base: any;

  constructor(baseUrl: string) {
      Object.defineProperty(this, 'base', {
          get() {
              Object.defineProperty(this, 'base',
              { value: baseUrl, configurable: true});
              return this.base;
          },
          enumerable: false,
          configurable: true
      });
  }

  attachProperty(name: string, value: any, enumerable?: boolean) {
      Object.defineProperty(this, name,
      { value, writable: false, configurable: true, enumerable: enumerable || true });
  }
}

export class MemberApi extends Api {

  /**
  * This comment will show up when referencing this.apiConfig.apis.microservices.member.memberInfo
  */
  get MemberInfo() {
    this.attachProperty("MemberInfo", `${this.base}basic-info`);
    return this.MemberInfo;
  }

  constructor(baseUrl: string) {
    super(baseUrl + "member/api/");
  }
}

Angular How-to: Microsoft Dev 블로그의 편집 가능한 구성 파일이 최상의 솔루션입니다.dev 빌드 설정 또는 prod 빌드 설정을 구성할 수 있습니다.

컨테이너에서 실행되는 경우, 이 문서 https://pumpingco.de/blog/environment-variables-angular-docker/ 은 사용 방법을 보여줍니다.envsubst환경 변수를 통해 이 정적 컴파일 문제를 즉시 해결할 수 있습니다.

언급URL : https://stackoverflow.com/questions/43193049/app-settings-the-angular-way

반응형