diff --git a/.buildpacks b/.buildpacks index b2b0e4e7..a73061c5 100644 --- a/.buildpacks +++ b/.buildpacks @@ -1,3 +1,3 @@ https://github.com/heroku/heroku-buildpack-nodejs.git -https://github.com/mars/create-react-app-inner-buildpack.git#v3.0.0 -https://github.com/heroku/heroku-buildpack-static.git +https://github.com/mars/create-react-app-inner-buildpack.git#v9.0.0 +https://github.com/heroku/heroku-buildpack-static.git#21c1f5175186b70cf247384fd0bf922504b419be diff --git a/README.md b/README.md index 892ad23a..7905dee9 100644 --- a/README.md +++ b/README.md @@ -1,363 +1,12 @@ Heroku Buildpack for create-react-app ===================================== -Deploy React.js web apps generated with [create-react-app](https://github.com/facebookincubator/create-react-app). Automates deployment with the built-in bundler and serves it up via [Nginx](http://nginx.org/en/). See the [introductory blog post](https://blog.heroku.com/deploying-react-with-zero-configuration) and entry in [Heroku elements](https://elements.heroku.com/buildpacks/mars/create-react-app-buildpack). +After a long, useful run, this buildpack is now at its end of life πŸŒ… -* 🚦 [Purpose](#purpose) -* ⚠️ [Requirements](#requires) -* πŸš€ [Quick Start](#quick-start) -* πŸ›  [Usage](#usage) - 1. [Generate a React app](#generate-a-react-app) - 1. [Make it a git repo](#make-it-a-git-repo) - 1. [Create the Heroku app](#create-the-heroku-app) - 1. [Commit & deploy ♻️](#commit--deploy-️) - 1. [Continue Development](#continue-development) -* πŸ‘“ [Customization](#customization) - * [Web server](#web-server) - * [Routing clean URLs](#routing-clean-urls) - * [HTTPS-only](#https-only) - * [Proxy](#proxy) - * [Environment variables](#environment-variables) - * [Set vars on Heroku](#set-vars-on-heroku) - * [Set vars for local dev](#set-vars-for-local-dev) - * [Compile-time vs Runtime](#compile-time-vs-runtime) - * [Compile-time config](#compile-time-configuration) - * [Runtime config](#runtime-configuration) - * [using an Add-on's config](#add-on-config-vars) -* πŸ•΅οΈΒ [Troubleshooting](#troubleshooting) -* πŸ“ [Version compatibility](#version-compatibility) -* πŸ™ [Architecture](#architecture-) +The underlying [static web server buildpack](https://github.com/heroku/heroku-buildpack-static) is deprecated and will not be supported on Heroku-22 or newer stacks. ------ +Please look into using [Next.js](https://nextjs.org) or [Remix](https://remix.run) to develop React apps which are deployable using the [Node.js buildpack](https://github.com/heroku/heroku-buildpack-nodejs). -Purpose -------- +---------- -**This buildpack deploys a React UI as a static web site.** The [Nginx](http://nginx.org/en/) 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](https://github.com/mars/heroku-cra-node). See also: [create-react-app + Rails 5 server](https://medium.com/superhighfives/a-top-shelf-web-stack-rails-5-api-activeadmin-create-react-app-de5481b7ec0b). - -Requires --------- - -* [Heroku](https://www.heroku.com/home) - * [command-line tools (CLI)](https://toolbelt.heroku.com) - * [a free account](https://signup.heroku.com) -* [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) -* [Node.js](https://nodejs.org) -* [create-react-app](https://github.com/facebookincubator/create-react-app) - * `npm install -g create-react-app` - -Quick Start ------------ - -Ensure [requirements](#requires) are met, then execute the following in a terminal. - -✏️ *Replace `$APP_NAME` with a name for your unique app.* - -```bash -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 - -```bash -create-react-app my-app -cd my-app -``` - -* If [yarn](https://yarnpkg.com) is installed locally, the new app will use it instead of [npm](https://www.npmjs.com). - -### Make it a git repo - -```bash -git init -``` - -At this point, this new repo is local, only on your computer. Eventually, you may want to [push to Github](#push-to-github). - -### Create the Heroku app - -```bash -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](https://devcenter.heroku.com/articles/creating-apps#creating-a-named-app) & its URL `https://my-app-name.herokuapp.com` -* sets the [buildpack](https://devcenter.heroku.com/articles/buildpacks) to deploy a `create-react-app` app -* configures the [`heroku` remote](https://devcenter.heroku.com/articles/git#creating-a-heroku-remote) in the local git repo, so `git push heroku master` will push to this new Heroku app. - -### Commit & deploy ♻️ - -```bash -git add . -git commit -m "Start with create-react-app" -git push heroku master -``` - -### Visit the app's public URL in your browser - -```bash -heroku open -``` - -### Visit the Heroku Dashboard for the app - -Find the app on [your dashboard](https://dashboard.heroku.com). - -### Continue Development - -Work with your app locally using `npm start`. See: [create-react-app docs](https://github.com/facebookincubator/create-react-app#getting-started) - -Then, commit & deploy ♻️ - -### Push to Github - -Eventually, to share, collaborate, or simply back-up your code, [create an empty repo at Github](https://github.com/new), 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](https://github.com/heroku/heroku-buildpack-static#configuration). - -The default `static.json`, if it does not exist in the repo, is: - -```json -{ "root": "build/" } -``` - -### Routing clean URLs - -[React Router](https://github.com/ReactTraining/react-router) (not included) may easily use 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` with React Router v3](https://github.com/ReactTraining/react-router/blob/v3/docs/guides/Histories.md#browserhistory) & [`BrowserRouter` with v4](https://reacttraining.com/react-router/web/api/BrowserRouter): - -```json -{ - "root": "build/", - "routes": { - "/**": "index.html" - } -} -``` - -πŸ‘“ See [custom routing w/ the static buildpack](https://github.com/heroku/heroku-buildpack-static#custom-routes). - -### HTTPS-only - -Enforce secure connections by automatically redirecting insecure requests to **https://**, in `static.json`: - -```json -{ - "https_only": true -} -``` - -Prevent downgrade attacks with [HTTP strict transport security](https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security). Add HSTS `"headers"` to `static.json`: - -```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](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) is not available on the backend. - -Configure using [Proxy Backends from the static site buildpack](https://github.com/heroku/heroku-buildpack-static/blob/master/README.md#proxy-backends). Add `"proxies"` to `static.json`: - -```json -{ - "proxies": { - "/api/": { - "origin": "${API_URL}" - } - } -} -``` - -Then, point the React UI app to a specific backend API: - -```bash -heroku config:set API_URL="https://api.example.com" -``` - - -### Environment variables - -[`REACT_APP_*` environment variables](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-custom-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.* - -### [Set vars on Heroku](https://devcenter.heroku.com/articles/config-vars) - -```bash -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: - -```bash -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](https://github.com/facebookincubator/create-react-app#npm-run-build) the app supports variables set at runtime, applied as each web dyno starts-up. - -Requirement | [Compile-time](#compile-time-configuration) | [Runtime](#runtime-configuration) -:--- |:---:|:---: -never changes for a build | βœ“ | -support for [continuous delivery](https://www.heroku.com/continuous-delivery) | | βœ“ -updates immediately when setting new [config vars](https://devcenter.heroku.com/articles/config-vars) | | βœ“ -different values for staging & production (in a [pipeline](https://devcenter.heroku.com/articles/pipelines)) | | βœ“ -ex: `REACT_APP_BUILD_VERSION` (static fact about the bundle) | βœ“ | -ex: `REACT_APP_DEBUG_ASSERTIONS` ([prune code from bundle](https://webpack.github.io/docs/list-of-plugins.html#defineplugin)) | βœ“ | -ex: `REACT_APP_API_URL` (transient, external reference) | | βœ“ -ex: `REACT_APP_FILEPICKER_API_KEY` ([Add-on config vars](#add-on-config-vars)) | | βœ“ - -### Compile-time configuration - -♻️ The app must be re-deployed for compiled changes to take effect. - -```bash -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](https://www.npmjs.com/package/@mars/heroku-js-runtime-env): - -```bash -npm install @mars/heroku-js-runtime-env --save -``` - -Then, require/import it to use the vars within components: - -```javascript -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 ( - Runtime env var example: { env.REACT_APP_HELLO } - ); - } -} -``` - -⚠️ *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](https://devcenter.heroku.com/articles/buildpack-api#profile-d-scripts) to make variables visible to the React app by prefixing them with `REACT_APP_`. - -1. create `.profile.d/000-react-app-exports.sh` -1. make it executable `chmod +x .profile.d/000-react-app-exports.sh` -1. add an `export` line for each variable: - - ```bash - export REACT_APP_ADDON_CONFIG=${ADDON_CONFIG:-} - ``` -1. set-up & use [Runtime configuration](#runtime-configuration) to access the variables - -For example, to use the API key for the [Filestack](https://elements.heroku.com/addons/filepicker) JS image uploader: - -```bash -export REACT_APP_FILEPICKER_API_KEY=${FILEPICKER_API_KEY:-} -``` - -Troubleshooting ---------------- - -1. Check this README to see if it already mentions the issue. -1. Search our [issues](https://github.com/mars/create-react-app-buildpack/issues?utf8=βœ“&q=is%3Aissue%20) to see if someone else has experienced the same problem. -1. Search the internet for mentions of the error message and its subject module, e.g. `ENOENT "node-sass"` -1. File a new [issue](https://github.com/mars/create-react-app-buildpack/issues/new). 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](#create-the-heroku-app) will always deploy an app with the most recent version of this buildpack. - -[Releases are tagged](https://github.com/mars/create-react-app-buildpack/releases), so you can lock an app to a specific version, if that kind of determinism pleases you: - -```bash -heroku buildpacks:set https://github.com/mars/create-react-app-buildpack.git#v1.2.1 -``` - -✏️ *Replace `v1.2.1` with the desired [release tag](https://github.com/mars/create-react-app-buildpack/releases).* - -♻️ Then, commit & deploy to rebuild on the new buildpack version. - - -Architecture πŸ™ ------------- - -This buildpack composes several buildpacks (specified in [`.buildpacks`](.buildpacks)) to support **no-configuration deployment** on Heroku: - -1. [`heroku/nodejs` buildpack](https://github.com/heroku/heroku-buildpack-nodejs) - * complete Node.js enviroment to support the webpack build - * `node_modules` cached between deployments -2. [`mars/create-react-app-inner-buildpack`](https://github.com/mars/create-react-app-inner-buildpack) - * enables [runtime environment variables](#runtime-configuration) - * generates the [default `static.json`](#customization) - * performs the production build for create-react-app, `npm run build` -3. [`heroku/static` buildpack](https://github.com/heroku/heroku-buildpack-static) - * [Nginx](http://nginx.org/en/) web server - * handy static website & SPA (single-page app) [customization options](https://github.com/heroku/heroku-buildpack-static#configuration) - - -### General-purpose SPA deployment - -[Some kind feedback](https://github.com/mars/create-react-app-buildpack/issues/2) 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: - -* `npm run build` performs the transpile/bundling -* the file `build/index.html` or [the root specified in `static.json`](#customization) exists at runtime. +Original README is still available on the [final release tag](https://github.com/mars/create-react-app-buildpack/tree/v9.0.1). diff --git a/bin/compile b/bin/compile index 860f7469..5f6c2ac7 100755 --- a/bin/compile +++ b/bin/compile @@ -23,6 +23,17 @@ CACHE_DIR=$2 ENV_DIR=$3 BP_DIR=`cd $(dirname $0); cd ..; pwd` +# Switch to new Node auto build behavior ahead of release +export NEW_BUILD_SCRIPT_BEHAVIOR=true + +echo +echo "=====! create-react-app-buildpack has reached end-of-life πŸŒ…" +echo " This build may succeed, but the buildpack is no longer maintained." +echo " On the Heroku-22 stack and beyond, this may fail to build at all." +echo +echo " Please consider migrating to https://nextjs.org or https://remix.run to develop React apps which are deployable using Heroku's Node.js buildpack https://github.com/heroku/heroku-buildpack-nodejs, or you may develop your own create-react-app deployment with Node.js and Nginx buildpacks." +echo + # Use architecture of multi-buildpack to compose behavior. # https://github.com/heroku/heroku-buildpack-multi cp $BP_DIR/.buildpacks $BUILD_DIR/.buildpacks @@ -31,12 +42,6 @@ branch="" dir=$(mktemp -t buildpackXXXXX) rm -rf $dir -# Set env vars for the inner buildpacks in `.buildpacks` -# * install build tooling (devDependencies) with npm & Yarn -# * used only during compile, as the runtime is a static web server -export NPM_CONFIG_PRODUCTION=false -export NODE_ENV=development - echo "=====> Downloading Buildpack: $url" if [[ "$url" =~ \.tgz$ ]] || [[ "$url" =~ \.tgz\? ]]; then diff --git a/bin/test b/bin/test new file mode 100755 index 00000000..f0c90e59 --- /dev/null +++ b/bin/test @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# bin/test-compile BUILD_DIR CACHE_DIR ENV_DIR + +# Hint to the test runner to exit when complete instead of watching. +export CI=true + +# Test runner copied from Node buildpack: +# https://github.com/heroku/heroku-buildpack-nodejs/blob/master/bin/test + +BUILD_DIR=${1:-} +if yarn --version > /dev/null 2>&1; then + cd "$BUILD_DIR" && yarn test +else + cd "$BUILD_DIR" && npm test +fi \ No newline at end of file diff --git a/bin/test-compile b/bin/test-compile new file mode 100755 index 00000000..e4e10c4f --- /dev/null +++ b/bin/test-compile @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# bin/test-compile BUILD_DIR CACHE_DIR ENV_DIR + +# Test compiler copied from Node buildpack: +# https://github.com/heroku/heroku-buildpack-nodejs/blob/master/bin/test-compile + +NODE_ENV=test "$(dirname ${0:-})/compile" "$1" "$2" "$3" \ No newline at end of file