Search overlay panel for performing site-wide searches

Build Your Next Big Thing on Heroku. Sign Up Now!

Front-End Web Deep Dive: Runtime Config

Heroku introduced the Twelve-Factor App philosophy in 2009 for building modern, scalable, and maintainable cloud-native applications. One of its core tenets is Config:

An app’s config is everything that is likely to vary between deploys (staging, production, developer environments, etc).

While this is a solved problem for the server-side, it remains a challenge for the front-end. Most static web apps have configuration, such as environment variables accessed via process.env, compiled directly into their build artifacts. Because these values are “baked in” during the build, a full re-build is required just to change an API URL when an app is promoted from staging to production.

Ten years ago, we published create-react-app-buildpack to solve this problem on Heroku for apps developed with the create-react-app tool. This buildpack performed a lot of magic to inject REACT_ environment variables into the JavaScript bundle at runtime. Despite its popularity (with over 3.2K stars on Github), we never succeeded in generalizing the architecture because of the security risks involved in altering the final JavaScript bundle.

We have evolved that approach. Runtime configuration has been brought to the Front-End Web Cloud Native Buildpack in a way that is standard, secure, and requires zero re-builds. By revisiting Twelve-Factor principles through the lens of modern web standards, we have created a strategy that works for any framework.

Env as HTML data

With the Heroku Front-End Web CNB, runtime configuration is managed through a web-standard approach: writing environment variables directly into the HTML document as data-* attributes. This method avoids the pitfalls of bundle-injections by treating the HTML entry point as the configuration source of truth.

How it works

To get started, set your runtime configuration of your static web app using the PUBLIC_WEB_ prefix. For example:

PUBLIC_WEB_API_URL=https://api-staging.example.com

Then, whenever the included static web server starts-up, whether using docker run or Heroku deployment, these variables will be written into the static HTML document <head> element as data-* attributes.

<html>
<head data-public_web_api_url="https://api-staging.example.com">
  <title>Example</title>
</head>
<body>
  <h1>Example</h1>
</body>
</html>

You can even include default values for these attributes in your source document, and they will be overwritten at runtime by values set in the environment.

These attribute values are accessible directly within the JavaScript app via document.head.dataset.

<html>
<head data-public_web_api_url="https://api-staging.example.com">

  <title>Example</title>

  <script>
    const response = await fetch(document.head.dataset.public_web_api_url, {
      method: "POST",
      // …
    });
  </script>

</head>
<body>
  <h1>Example</h1>
</body>
</html>

Every time the static web server starts, the current PUBLIC_WEB_ configuration is loaded into the app. This supports instant environment variable changes without rebuilding.

For more about using runtime configuration, see the Dev Center article.

Universal compatibility and security

This Env-as-HTML-Data technique is universally compatible. It injects runtime configuration into browser apps as safe, standard, HTML data-* attributes without any framework or platform bias. Because the configuration is part of the HTML document itself, there is no conflict with Content-Security-Policy (CSP), Subresource Integrity (SRI), or other browser safeguards.

Adapting a pre-existing app to this new runtime configuration strategy may require refactoring how its environment values are read to avoid capturing them at build-time.

Crafted from experience

At Heroku, our own front-end engineering team is adopting the Front-End Web Cloud Native Buildpack (CNB) to deliver customer-facing interfaces like dashboard.heroku.com. We’d love to hear your feedback and ideas in the Front-end Web Cloud Native Buildpack’s GitHub issues.

Ready to Get Started?

Stay focused on building great data-driven applications and let Heroku tackle the rest.

Talk to A Heroku Rep   Sign Up Now