Angular: Using Config File After Build
Background: I've got an Angular app being built by TeamCity and deployed by Octopus Deploy to multiple environments. For each environment, I also have a different API Url that it will talk to.
The whole source code covered in this post is available here
Using the default Angular environment variables is not ideal in this case, because I don't really want to build the application multiple times, I want to build it once and let Octopus change some configuration files depending on the environment.
My idea was simple: add a config.json file to the assets folder, and then inject this file some how in the module and use it.
Not that simple after all, but I got there. Let's see how I did it.
-
I did add a config.json file to the assets folder and when building the app with
ng buildthe file is automatically added todist\assetsfolder. -
I couldn't find any simple way to just get a
config.jsonfrom the assets folder and inject into a module. So I ended up having to create a service for that which would use the default javascriptXMLHttpRequestto do the job.
@Injectable()
export class ConfigService {
public config: any;
constructor(private http: Http) {
}
loadJSON(filePath) {
const json = this.loadTextFileAjaxSync(filePath, "application/json");
return JSON.parse(json);
}
loadTextFileAjaxSync(filePath, mimeType) {
const xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filePath, false);
if (mimeType != null) {
if (xmlhttp.overrideMimeType) {
xmlhttp.overrideMimeType(mimeType);
}
}
xmlhttp.send();
if (xmlhttp.status == 200) {
return xmlhttp.responseText;
}
else {
return null;
}
}
}
- That actually was not enough to inject it into module, because what I had before was
{ provide: API_BASE_URL, useValue: 'http://localhost:4444' }, as I'm using a generated service created by NSWAG. So I had to find a different way to achieve that. I had to create aConfigFactoryto use in the provider likeuseFactory: ConfigFactory. That's how theConfigFactorylooks like:
export function ConfigFactory(configService: ConfigService, file: string, property: string) {
return configService.loadJSON(file)[property];
}
- Now I just need to use the
ConfigFactory. I added 3 extra entries to my list of providers:CONFIGPATHis path to theconfig.jsonfile,APIURLVARis the variable I'm going to extract from theconfig.jsonand finally theAPI_BASE_URLis the one using theConfigFactory.
{ provide: 'CONFIGPATH', useValue: '/assets/config.json' },
{ provide: 'APIURLVAR', useValue: 'API_BASE_URL' },
{
provide: API_BASE_URL, useFactory: ConfigFactory,
deps: [ConfigService, 'CONFIGPATH', 'APIURLVAR']
}]
Now you can build your app once and modify the API Url based on the environment you're going to deploy to, which is easily configured in Octopus Deploy.
Hope it helps.
Cheers,
Thiago.