I am developing an angular application which is a product and deployed to multiple clients. Clients will take this angular application and host it in their servers. So the Services' url will be different for the clients. I have seen solutions that talk about dev, prod. But that will not be applicable in this case. I am looking for a config file that is similar to .net config file. I have created a separate app.config.ts file but that gets built when I do ng build. I am looking for a solution where I can deploy the app to any client with out them to build it again.
import { InjectionToken } from "@angular/core";
export let APP_CONFIG = new InjectionToken("app.config");
export interface IAppConfig {
apiEndpoint: string;
}
export const AppConfig: IAppConfig = {
apiEndpoint: "http://88.87.86.999/"
};
Because these files are static, you can host them on any web server capable of serving files; such as Node. js , Java, . NET, or any backend such as Firebase, Google Cloud, or App Engine.
To deploy an angular application in tomcat we need to build the application using the ng tool. For this demo, I am going to build a simple default angular application using below command. To create an angular application run the following command in command prompt as shown below.
What you can do it host the config file in json format in the assets folder and retrieve it dynamically. You need to make sure that you retrieve it before the app starts, that way it can be available in components/services when they need it. For that, you can use the APP_INITIALIZER Token
Step #1: put your json configuration files under src/assets/config/conf.json (json format, not ts format since there is no TS compiler in prod mode)
Step #2: Add a new config service
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 apiEndpoint: 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) => {
this.http.get('/assets/config/config.json').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);
});
});
}
}
Step #3: In your main module, add this before declaring the module
/**
* Exported function so that it works with AOT
* @param {AppConfigService} configService
* @returns {Function}
*/
export function loadConfigService(configService: AppConfigService): Function
{
return () => { return configService.load() };
}
Step #4: Modify the module providers to add this
providers: [
…
AppConfigService,
{ provide: APP_INITIALIZER, useFactory: loadConfigService , deps: [AppConfigService], multi: true },
],
Step 5: In your code, use the config
import {APP_CONFIG} from "../services/app-config.service";
//…
return APP_CONFIG.configXXX;
Now, you can ship the app to multiple clients; each client just need to have theyr specific parameter in conf.json file
For the config to be loaded initially and use it even when bootstrapping the AppModule, we used this simple solution in main.ts.
notice we queued the
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
inside an async function that waits for the fetching of a config file.
(async () => {
// console.time()
const response = await fetch('./assets/config/conf.json');
const json = await response.json();
Object.entries(json).forEach(([key, value]) => {
environment[key] = value;
});
// console.timeEnd()
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
})();
the config file is located in the assets and is replaced accordingly by the deployment job.
meaning we have environment based config:
time of fetching on for us takes about 40 milliseconds (practically nothing. uncomment the console.time to check estimations in your own projects). I doubt it will consume too much time on any project as it is fetched from a local file. good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With