Document multiple build environments via `env-cmd`
See original GitHub issueThe term “development environment”, “test environment” and “production environment” is used differently across the contexts and sometimes cause confusion for users.
-
create-react-app defines the environment name by the state of app code build: “development” means the code is not minified and run in live reload mode on local machines, “test” means the code is executing in unit test process, “production” means the code is minified and optimized with source map. I’ll call this “development build”, “test build” and “production build”.
-
Mean while, in large portion of the software industry, these terms are used differently:
In the diagram above, I’ll call them deploy environment, each deploy environment is a set of all the services that linked and worked with each other in an isolated place (servers/VPN).
“Frontend” is where create-react-app lives, and this all run “production build” of the app, which means the code is minified and optimized.
The problem
Regarding this document: https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-custom-environment-variables
NODE_ENV
always resolves toproduction
when built withyarn build
, even if we try to runNODE_ENV=staging yarn build
.- There is no effective way to define different environment variables for each deploy environments. This is a real need.
- There is no or very little benefit to define different environment variables for development build and production build, most of the time it is the same.
What I have been doing to resolve this
- Put all the environment variables in source code and use domain name to identify the deployment environment the app is running. This reveals environment variables of all deployment environments, not so good.
- or
- Having different package.json scripts to build for different deployment environments:
yarn build-staging
,yarn build-production
,… In the script, it creates.env
file according the deployment environment and build. Ex:mv env/staging.env ./.env && yarn build
. - or
- On each deployment environment I setup a mini server that hosts an API endpoint and return environment variables for that deployment environment. (ex:
https://staging-my-app.com/env
)
Better way?
What is the best practice here? Have anyone of you run into this problem? How did you do it? Should create-react-app
do something about this? Please share, thanks!
Issue Analytics
- State:
- Created 6 years ago
- Reactions:10
- Comments:7 (3 by maintainers)
Top GitHub Comments
The easiest way to achieve this is via
.env
files, injecting each variable you’d like to use in your app, most close to your second solution.Instead, create one for each environment.
.env.staging
.env.qa
Then you can just add some extra scripts in your
package.json
:In this scenario,
.env.production
would only be used for fallback if a variable isn’t specified in.env.staging
or.env.qa
.You described the situation well 🙂
The default use of
NODE_ENV
is intentional and is solely used to distinguish between local development builds, unit tests, and optimized production builds. You can think of'production'
as a generic “distribution” build, not necessarily a build literally destined for a public-facing production server.As you mentioned, it is common to have a few types of server environments for an application. These should all run the optimized
NODE_ENV=production
build, so that you can test your app with production-level performance. In order to programmatically differentiate between environments at runtime, you’ll need to use a different environment variable, something other thanNODE_ENV
.Create-react-app mandates that you prefix any custom environment variables with
REACT_APP_
. You can set custom prefixed environment variables from a CLI, see this section of the readme. In Bash for example, you could run:You can access the variable in your app with
process.env.REACT_APP_DIST_ENV
. For example:I haven’t personally tried this with create-react-app, but check out the cross-env package. It allows setting environment variables in a cross-platform manner. You could then simplify your
package.json
scripts to something like this:Then run
yarn build:staging
on any machine to compile an optimized build ready to be deployed on a staging server.