Como fazer: Arquivos de Configuração Editáveis

Premier Developer

Premier

The Portuguese translation for this article is provided by App Dev Manager Julio Madeira. English version available here.


O Angular-CLI é a maneira recomendada de criar um aplicativo pronto para produção, completo com agrupamento, atualização e testes. Um Aplicativo desenvolvido com o Angular-CLI vem com um mecanismo para criar versões especificas para cada ambiente, contudo, esses arquivos de configurações vem em formato TypeScript e não permitem que sejam editados pela equipe de TI ou por processos automatizados de Deployment, como por exemplo o VSTS.

Esse Post vai explicar em alguns passos e exemplos como usar um arquivos JSON de configuração que pode ser customizado para múltiplos ambientes.

Defina a Interface TypeScript para configuração:

O uso de interfaces numa App Angular, provê uma serie de funcionalidades (intellisense) e seguras (type-safety) para as entidades que você estiver usando. No exemplo abaixo, vamos usar um arquivo-exemplo como “Arquivo de Configuração”:

app-config.model.ts

export interface IAppConfig {
    env: {
        name: string;
    };
    appInsights: {
        instrumentationKey: string;
    };
    logging: {
        console: boolean;
        appInsights: boolean;
    };
    aad: {
        requireAuth: boolean;
        tenant: string;
        clientId: string;

    };
    apiServer: {
        metadata: string;
        rules: string;
    };
}

Crie um arquivo de configuração JSON fils

A convenient place to store configuration files is under the assets folder of your project. Using the interface defined above, sample files could look as follows:

Um local conveniente para armazenar arquivos de configuração está na pasta “Assets” do seu projeto. Usando a interface definida acima, os arquivos de exemplos podem ter a seguinte aparência:

assets\config\config.dev.json

{
    "env": {
    "name": "DEV"
     },
    "appInsights": {
    "instrumentationKey": "<dev-guid-here>"
     },
    "logging": {
    "console": true,
    "appInsights": false
    },
    "aad": {
    "requireAuth": true,
    "tenant": "<dev-guid-here>",
    "clientId": "<dev-guid-here>"
    },
    "apiServer": {
    "metadata": "https://metadata.demo.com/api/v1.0/",
    "rules": "https://rules.demo.com/api/v1.0/"
    }
}

assets\config\config.deploy.json (Observe os espaços reservados que são substituídos durante a implantação)

{
    "env": {
    "name": "#{envName}"
    },
    "appInsights": {
    "instrumentationKey": "#{appInsightsKey}"
    },
    "logging": {
    "console": true,
    "appInsights": true
    },
    "aad": {
    "requireAuth": true,
    "tenant": "#{aadTenant}",
    "clientId": "#{aadClientId}"
    },
    "apiServer": {
    "metadata": "https://#{apiServerPrefix}.demo.com/api/v1.0/",
    "rule": "https://#{apiServerPrefix}.demo.com/api/v1.0/",
    }
}

Continue a usar o “environment.ts“ com o build do Angular-CLI

A Angular-CLI cria vários arquivos de ambiente TypeScript na pasta de ambientes. Eles ainda serão usados, mas contêm apenas o nome do ambiente.

environments\environment.dev.json

export const environment = {
    name: 'dev'
};

environments\environment.deploy.json

export const environment = {
    name: 'deploy'
};

angular.json

"projects": {
  "my-app": {
    "architect": {
      "build": {
        "configurations": {
          "deploy": {
            "fileReplacements": [
              {
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.deploy.ts"
              }
            ],
            . . .
          }
        }
      },
      "serve": {
        . . .
        "configurations": {
          "deploy": {
            "browserTarget": "my-app:build:deploy"
          }

Crie um serviço para ler o arquivo de Config

Este serviço lerá o arquivo de configuração correto e armazenará o resultado em um campo estático nesta classe.

app.config.ts (Observe o uso da interface definida acima e a convenção de nomenclatura do arquivo de configuração para recuperar o arquivo correto.)

import { Injectable } from '@angular/core’;
import { HttpClient } from '@angular/common/http';
import { environment } from '../environments/environment';
import { IAppConfig } from './models/app-config.model';
@Injectable()
export class AppConfig {
    static settings: IAppConfig;
    constructor(private http: HttpClient) {}
    load() {
        const jsonFile = `assets/config/config.${environment.name}.json`;
        return new Promise<void>((resolve, reject) => {
            this.http.get(jsonFile).toPromise().then((response : IAppConfig) => {
               AppConfig.settings = <IAppConfig>response;
               resolve();
            }).catch((response: any) => {
               reject(`Could not load file '${jsonFile}': ${JSON.stringify(response)}`);
            });
        });
    }
}

Carregue o arquivo de Config antes de criar a Aplicação

Angular inclui um token chamado APP_INITIALIZER que permite ao nosso aplicativo executar código quando o aplicativo é inicializado. No módulo do aplicativo, use esse token para chamar o método load em nosso serviço de configuração. Como nosso método retorna uma promessa/promissoe, o Angular atrasará a inicialização até que a promessa/promisse seja resolvida.

app.module.ts

import { APP_INITIALIZER } from '@angular/core';
import { AppConfig } from './app.config';
 
export function initializeApp(appConfig: AppConfig) {
  return () => appConfig.load();
}
@NgModule({
    imports: [ , , , ],
    declarations: [ . . . ],
    providers: [
       AppConfig,
       { provide: APP_INITIALIZER,
         useFactory: initializeApp,
         deps: [AppConfig], multi: true }
    ],
    bootstrap: [
      AppComponent
    ]
})
export class AppModule { }

Consuma as configurações da App através de toda a aplicação

As configurações agora estão disponíveis em qualquer lugar do aplicativo e incluem a verificação de tipo fornecida pela interface.

export class DataService {
    protected apiServer = AppConfig.settings.apiServer;
    . . .
    if (AppConfig.settings.aad.requireAuth) { . . . }
}
export class LoggingService {
    . . .
    instrumentationKey: AppConfig.settings && AppConfig.settings.appInsights ?
                        AppConfig.settings.appInsights.instrumentationKey : ''
    . . .
    if (AppConfig.settings && AppConfig.settings.logging) { . . . }
}

Nota: para criar uma versão de produção do aplicativo usando um nome de ambiente diferente de prod, use este comando:

ng build –configuration=deploy

 

0 comments

Leave a comment