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 build
the file is automatically added todist\assets
folder. -
I couldn't find any simple way to just get a
config.json
from the assets folder and inject into a module. So I ended up having to create a service for that which would use the default javascriptXMLHttpRequest
to 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 aConfigFactory
to use in the provider likeuseFactory: ConfigFactory
. That's how theConfigFactory
looks 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:CONFIGPATH
is path to theconfig.json
file,APIURLVAR
is the variable I'm going to extract from theconfig.json
and finally theAPI_BASE_URL
is 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.