Serving environment variables dynamically to your web app can be challenging. Here are two suggestions for tackling it properly.
Be it a public key for payments, Google Analytics ID, or other tokens and settings, there are client-side constants which deserve to be configurable. Developers usually utilize either REACT_APP_ prefix or Webpack DefinePlugin to enable such an option. However, both the approaches face a common drawback: they bake-in the values at compile-time.
If you are building small apps or your project is in the development stage, compile-time replacement might be a suitable option. It could also work well in case of build-specific configuration, e.g. to differentiate a development, test, or production build.
However, problems arise when you want to have a single build and deploy multiple instances, perhaps to show a ready-to-deploy version of the app to your customer while running another version in your production environment. In such a case you would want these two instances to have a slightly different configuration. That’s why you use environment variables in the first place, right?
Choose proper solution
One thing you can do is to read the configuration at runtime on server-side and then make these values available to the browser. You can import them statically on page-load by inserting a
<script> tag into your index.html. Another possibility is to read them dynamically using
The former (
The latter (
XMLHttpRequest) gives you better control and is less likely to have issues with caching. You will need to code a little more. It employs
XMLHttpRequest to fetch the variables meaning that the client-side code needs to account for the fact that the configuration will be loaded asynchronously.
Check out the sample project on GitHub
I’ve created a sample project that illustrates both approaches. The code of the sample project is available on GitHub. I have commented it extensively so don’t be afraid to explore the codebase for inspiration. No reverse engineering required.
Security deserves special attention as it is common practice to put sensitive information such as passwords for third-party services into environment variables to avoid storing them in the repo. I strongly recommend that you validate which configuration variables are published to the client. You certainly don’t want to make your credentials or private keys available to the entire internet!
In conclusion, the main advantage of the approach I am proposing is that you can deploy several instances of a single build with different configurations, rather than having to create a separate build for each one.