Compiled config vs runtime config
See original GitHub issue💚 The custom environment variables feature.
Update February 2017: We devised a solution for runtime config on Heroku. create-react-app-buildpack now supports runtime environment variables by way of injecting values into the javascript bundle at runtime. This is still an open question for other runtimes and deployment techniques.
This feature leverages Webpack’s DefinePlugin which is explained as:
…global constants which can be configured at compile time.
The issue is not all configuration should be compiled into an application.
Things that are stable between environments (dev, staging, production) of an app make sense to compile-in:
- version number
- commit sha/number
- browser support flags
Things that change between environments would be better provided dynamically from the current runtime:
- URLs of an APIs (may change for each environment)
- secret tokens (may change for each user or request)
Ideally a bundle could be tested in CI, then promoted through environments to production, but compiling all of these values into the bundle means that every promotion requires rebuild.
I’ve used Node to serve single-page apps in the past with a base HTML template that gets environment variables set via inline <script>
at runtime; even used a server-side Redux reducer to capture process.env
values into an initial state.
Now, I’m trying to find a good solution to the conflation of runtime configuration values being compiled into the bundle.
create-react-app
is clearly focused on producing a bundle that can be used anywhere.
Is this project open to solutions/hooks for injecting runtime variables, or is this wandering into npm run eject
territory?
Issue Analytics
- State:
- Created 7 years ago
- Reactions:30
- Comments:30 (11 by maintainers)
Top GitHub Comments
The Twelve-Factor App guide mentioned by @mars has a section about “build, release, run” cycle. It explains that the build stage is only about creating an executable that could run anywhere. It is the release stage that should be responsible for combining this executable with the the deployment environment configuration.
create-react-app
is really close to being able to generate builds deployable anywhere!Indeed, if merged, this PR #1489 will relieve apps not using the HTML5
pushState
history API to specify the URL on which they will be deployed.Then, the only remaining task to make
create-react-app
builds compliant with the Twelve-Factor App recommendations is to let the deployment environment specify some part of the configuration. In fact,create-react-app
documents how to use environment variables but they only work at compile time.One of the solutions to add support for runtime environment variables that is really simple and lightweight would be to add an
env.js
file inside thepublic
directory and load it in a script tag inindex.html
just before the main.js bundle.env.js
could have the following content:The
body
ofindex.html
would be:After running
npm run build
, you would find yourenv.js
file untounched underbuild/env.js
. You would then be able to edit this file manually directly on the deployment machine or through a small bash script to changeAPI_URL
tohttps://api.my-app.com
for instance.Should I submit a PR documenting this technique or even adding this
env.js
file to the public folder of the boilerplate ?Writing configuration values into a file is antithetical to 12-factor. Instead, always use runtime environment variables for configuration.
create-react-app [CRA] does not provide a production runtime. It only builds a static bundle. Runtime environment is not something solvable by CRA, unless it becomes prescriptive about deployment which is unlikely given its wide range of applications.
Solving this problem is about finding a way to set those variable values in the React app at runtime instead of buildtime. I know of two ways to accomplish this:
<script>
element inindex.html
with a Node/Express server. Then, use those globals within your React app. (This would need to be resolved for local development too.)This is a challenging topic 🤓 Bravo for trying to solve it 👏👏👏