Disclaimer for german readers: Dieser Artikel beschäftigt sich mit technischen Details. Falls sie auf der Suche nach Heigh-Level-Erklärungen sind, werden Sie in andern Artikeln eher fündig.
It shouldn’t take a rebuild to reconfigure an app for a certain environment. It should be build once and in each deployed state (test, nightly, demo, pre-prod, staging, prod, etc) have the configuration that applies on the server, respectivly environment.
The most common way to configure an app in a certain environment is by using environment variables. You can easily set them through .env files in Docker, Vagrant, AWS and other service providers.
To archive that, let’s start at the server side: A JavaScript-application runs on a webserver. It consists out of plain text files. While running on a client’s browser, there is now way for the JavaScript to access server values such as environment variables during runtime.
We need to inject the values, that life inside our server into the text files of our JavaScript application.
First, prepare a file called env.template.js
with the environment variables you expect.
(function (window) { window["env"] = window["env"] || {}; // Environment variables TEMPLATE window["env"]["title"] = "${TITLE}"; })(this);
And again, there is no pre-existing mechanism. Here we can see, we prepare that file with placeholders ${XYZ}
as strings. To inject the environment variables, that live on the server and thus can be differ from one environment to another.
To create a mechanism we need to run the following command on the server (this can be done during the deployment process to a certain environment, e.g. in an CI/CD-pipeline.
envsubst < /home/nonroot/htdocs/assets/env.template.js > /home/nonroot/htdocs/assets/env.js
What this does is, it takes all the environment variables, set to a certain value currently on the machine, and replaces all the placeholders ${XYZ}
that match.
For example if there was an environment variable TITLE
set to "This is a title"
, then any occurance of ${TITLE}
inside the file would be replaced by „This is a title“ (without the quotes). After that the new resulting file is written into a new file, here
/home/nonroot/htdocs/assets/env.js
The contents of the new file would look like the following snippet shows.
(function (window) { window["env"] = window["env"] || {}; // Environment variables TEMPLATE window["env"]["title"] = "This is a title"; })(this);
That is what we wanted to have. We had no pre-existing mechanism, that lets us access the environment variables on the server inside a certain environment. Now we have injected them very clean into our application.
We have them available, how to process them in our application?
There is nothing wrong with simply including the env.js
file in our index.html
, right into the header (of course you can export and import it, which would be slightly cleaner).
<!-- Load environment variables --> <script src="assets/env.js"></script>
Now, if the environemnt variable TITLE was declared on the machine the scripts are running on, window['env']['title']
should hold the value, in our case "This is a title"
as string. Globaly, everywhere in our application (maybe some kind of anti-pattern, you have the force. Seal it with dependency injection and so on) Easy?
Use the environment variable inside the environment files
The environment file in angular are a bit misleading. The implay, that you should have one file for each environment. I just look at environment.ts
and environment.prod.ts
. In the latter we can use our window[„env“] variable now.
export const environment = { production: true, title: window['env']['title'] || 'A default value for a title', };
That’s it. Comment if you like.