question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

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:closed
  • Created 7 years ago
  • Reactions:30
  • Comments:30 (11 by maintainers)

github_iconTop GitHub Comments

68reactions
tibdexcommented, May 17, 2018

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 the public directory and load it in a script tag in index.html just before the main.js bundle.

env.js could have the following content:

// This file will not end up inside the main application JavaScript bundle.
// Instead, it will simply be copied inside the build folder.
// The generated "index.html" will require it just before this main bundle.
// You can thus use it to define some environment variables that will
// be made available synchronously in all your JS modules under "src". 
//
// Warning: this file will not be transpiled by Babel and cannot contain
// any syntax that is not yet supported by your targeted browsers.

window.env = {
  // This option can be retrieved in "src/index.js" with "window.env.API_URL".
  API_URL: 'http://localhost:9090'
};

The body of index.html would be:

<body>
    <div id="root"></div>
    <!--
      Load "env.js" script before the main JavaScript bundle.
      You can use it to define "runtime" environment variables.
      Please open this file for more details.
    -->
    <script src="%PUBLIC_URL%/env.js"></script>
  </body>

After running npm run build, you would find your env.js file untounched under build/env.js. You would then be able to edit this file manually directly on the deployment machine or through a small bash script to change API_URL to https://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 ?

21reactions
marscommented, Feb 7, 2017

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:

  1. Render runtime environment values into global variables in a <script> element in index.html with a Node/Express server. Then, use those globals within your React app. (This would need to be resolved for local development too.)
  2. Deploy to Heroku using create-react-app-buildpack which supports runtime environment variables by way of injecting values into the javascript bundle at runtime.

This is a challenging topic 🤓 Bravo for trying to solve it 👏👏👏

Read more comments on GitHub >

github_iconTop Results From Across the Web

Compile-time vs. Runtime configuration of your Angular App
It basically means that you compile your configuration into your app, at the time when you compile and bundle it. If you're using...
Read more >
Compile-time vs. run-time configuration
From a miles-high perspective, there are three main considerations for compile-time vs runtime (or program-launchtime) configuration. Necessity.
Read more >
Compilation config settings - .NET - Microsoft Learn
Configures whether the just-in-time (JIT) compiler uses tiered compilation. Tiered compilation transitions methods through two tiers: The first ...
Read more >
Difference between compile and runtime configurations in ...
What is an implementation dependency? · Compile classpath – Those dependencies which are required for the JDK to be able to compile Java...
Read more >
C++ – Compile-time vs. run-time configuration
From a miles-high perspective, there are three main considerations for compile-time vs runtime (or program-launchtime) configuration. Necessity. Necessity ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found