Skip to content

Heroku Buildpack for create-react-app: static hosting for React.js web apps

License

Notifications You must be signed in to change notification settings

gabrielbauman/react-nginx-buildpack

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

64 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Heroku Buildpack for create-react-app

Deploy React.js web apps generated with create-react-app. Automates deployment with the built-in bundler and serves it up via Nginx. See the introductory blog post and entry in Heroku elements.


Purpose

This buildpack deploys a React UI as a static web site. The Nginx web server provides optimum performance and security for the runtime.

If your goal is to combine React UI + API (Node, Ruby, Python…) into a single app, then this buildpack is not the answer. The simplest combined solution is to use create-react-app + Node.js server. See also: create-react-app + Rails 5 server.

Requires

Quick Start

Ensure requirements are met, then execute the following in a terminal.

✏️ Replace $APP_NAME with a name for your unique app.

create-react-app $APP_NAME
cd $APP_NAME
git init
heroku create $APP_NAME --buildpack https://github.com/mars/create-react-app-buildpack.git
git add .
git commit -m "Start with create-react-app"
git push heroku master
heroku open

For explanation about these steps, continue reading the next section.

Usage

Generate a React app

create-react-app my-app
cd my-app
  • If yarn is installed locally, the new app will use it instead of npm.

Make it a git repo

git init

At this point, this new repo is local, only on your computer. Eventually, you may want to push to Github.

Create the Heroku app

heroku create $APP_NAME --buildpack https://github.com/mars/create-react-app-buildpack.git

✏️ Replace $APP_NAME with a name for your unique app.

This command:

  • sets the app name & its URL https://my-app-name.herokuapp.com
  • sets the buildpack to deploy a create-react-app app
  • configures the heroku remote in the local git repo, so git push heroku master will push to this new Heroku app.

Commit & deploy ♻️

git add .
git commit -m "Start with create-react-app"
git push heroku master

Visit the app's public URL in your browser

heroku open

Visit the Heroku Dashboard for the app

Find the app on your dashboard.

Continue Development

Work with your app locally using npm start. See: create-react-app docs

Then, commit & deploy ♻️

Push to Github

Eventually, to share, collaborate, or simply back-up your code, create an empty repo at Github, and then follow the instructions shown on the repo to push an existing repository from the command line.

Customization

Web server

The web server may be configured via the static buildpack.

The default static.json, if it does not exist in the repo, is:

{ "root": "build/" }

Routing clean URLs

By default, React Router (not included) uses hash-based URLs like https://example.com/index.html#/users/me/edit. This is nice & easy when getting started with local development, but for a public app you probably want real URLs like https://example.com/users/me/edit.

Create a static.json file to configure the web server for clean browserHistory URLs with React Router:

{
  "root": "build/",
  "clean_urls": false,
  "routes": {
    "/**": "index.html"
  }
}

HTTPS-only

Enforce secure connections by automatically redirecting insecure requests to https://, in static.json:

{
  "https_only": true
}

Prevent downgrade attacks with HTTP strict transport security. Add HSTS "headers" to static.json:

{
  "headers": {
    "/**": {
      "Strict-Transport-Security": "max-age=7776000"
    }
  }
}
  • max-age is the number of seconds to enforce HTTPS since the last connection; the example is 90-days

Proxy

Proxy XHR requests from the React UI in the browser to API backends. Prevent same-origin errors when CORS is not available on the backend.

Configure using Proxy Backends from the static site buildpack. Add "proxies" to static.json:

{
  "proxies": {
    "/api/": {
      "origin": "${API_URL}"
    }
  }
}

Then, point the React UI app to a specific backend API:

heroku config:set API_URL="https://api.example.com"

Environment variables

REACT_APP_* environment variables are supported with this buildpack.

🤐 Be careful not to export secrets. These values may be accessed by anyone who can see the React app.

heroku config:set REACT_APP_HELLO='I love sushi!'

Set vars for local dev

Requires at least create-react-app 0.7. Earlier versions only support Compile-time.

Create a .env file that sets a variable per line:

REACT_APP_API_URL=http://api.example.com
REACT_APP_CLIENT_ID=XyzxYzxyZ

Compile-time vs Runtime

Two versions of variables are supported. In addition to compile-time variables applied during build the app supports variables set at runtime, applied as each web dyno starts-up.

Requirement Compile-time Runtime
never changes for a build
support for continuous delivery
updates immediately when setting new config vars
different values for staging & production (in a pipeline)
ex: REACT_APP_BUILD_VERSION (static fact about the bundle)
ex: REACT_APP_DEBUG_ASSERTIONS (prune code from bundle)
ex: REACT_APP_API_URL (transient, external reference)
ex: REACT_APP_FILEPICKER_API_KEY (Add-on config vars)

Compile-time configuration

♻️ The app must be re-deployed for compiled changes to take effect.

heroku config:set REACT_APP_HELLO='I love sushi!'

git commit --allow-empty -m "Set REACT_APP_HELLO config var"
git push heroku master

Runtime configuration

Requires at least create-react-app 0.7.

Install the runtime env npm package:

npm install @mars/heroku-js-runtime-env --save

Then, require/import it to use the vars within components:

import React, { Component } from 'react';
import runtimeEnv from '@mars/heroku-js-runtime-env';

class App extends Component {
  render() {
    // Load the env object.
    const env = runtimeEnv();

    // …then use values just like `process.env`
    return (
      <code>Runtime env var example: { env.REACT_APP_HELLO }</code>
    );
  }
}

⚠️ Avoid setting backslash escape sequences, such as \n, into Runtime config vars. Use literal UTF-8 values only; they will be automatically escaped.

Add-on config vars

🤐 Be careful not to export secrets. These values may be accessed by anyone who can see the React app.

Use a custom .profile.d script to make variables visible to the React app by prefixing them with REACT_APP_.

  1. create .profile.d/000-react-app-exports.sh

  2. make it executable chmod +x .profile.d/000-react-app-exports.sh

  3. add an export line for each variable:

    export REACT_APP_ADDON_CONFIG=${ADDON_CONFIG:-}
  4. set-up & use Runtime configuration to access the variables

For example, to use the API key for the Filestack JS image uploader:

export REACT_APP_FILEPICKER_API_KEY=${FILEPICKER_API_KEY:-}

Troubleshooting

  1. Check this README to see if it already mentions the issue.
  2. Search our issues to see if someone else has experienced the same problem.
  3. Search the internet for mentions of the error message and its subject module, e.g. ENOENT "node-sass"
  4. File a new issue. Please include:
    • build log output
    • link to GitHub repo with the source code (if private, grant read access to @mars)

Version compatibility

This buildpack will never intentionally cause previously deployed apps to become undeployable. Using master as directed in the main instructions will always deploy an app with the most recent version of this buildpack.

Releases are tagged, so you can lock an app to a specific version, if that kind of determinism pleases you:

heroku buildpacks:set https://github.com/mars/create-react-app-buildpack.git#v1.2.1

✏️ Replace v1.2.1 with the desired release tag.

♻️ Then, commit & deploy to rebuild on the new buildpack version.

Architecture 🏙

This buildpack composes several buildpacks (specified in .buildpacks) to support no-configuration deployment on Heroku:

  1. heroku/nodejs buildpack
    • complete Node.js enviroment to support the webpack build
    • node_modules cached between deployments
  2. mars/create-react-app-inner-buildpack
  3. heroku/static buildpack

General-purpose SPA deployment

Some kind feedback pointed out that this buildpack is not necessarily specific to create-react-app.

This buildpack can deploy any SPA [single-page app] as long as it meets the following requirements:

About

Heroku Buildpack for create-react-app: static hosting for React.js web apps

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Shell 100.0%