Deploy pipelines (test, prod) based on environment vars are important for some apps.
As most static deploy options may not handle the npm run build by themselves (allowing to register stage specific env vars at design time), I think some README advice on how to manage stage specific env vars would be helpful to many.
Or perhaps an enhancement like
STAGE=MYSTAGE npm run build which selects the REACT_APP_MYSTAGE_SOMEVAR env var?
I think you can already use the NODE_ENV argument.
Faced the same issue, it seems it has been hardcoded here. Meanwhile I have just used another variable BUILD_ENV to work with my deployment dependent stuff. https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/scripts/build.js#L13
@vernondegoede The NODE_ENV actually decides on the type of build (optimized or not, etc.). This doesn't relate to multi-stage deployment so much, as I need different stages, but each with NODE_ENV === 'production'.
One could probably add everything into the environment and do something like
const publicKey = process.env[`REACT_APP_${process.env.REACT_APP_STAGE}_PUBLIC_KEY`]
for every env variable, but maybe there are more elegant solutions than this?
@bebbi Ideally you should keep environment variables in code generic, like REACT_APP_PUBLIC_KEY and before running your deployment script you can do
export REACT_APP_PUBLIC_KEY=$REACT_APP_STAGE_PUBLIC_KEY
This helps the rest of the code/deployment script remain common for different build environments. I use this practice personally to control circleci deployments
@islahul would you mind elaborating on what your deployments look like?
Or even your local dev, in the context of CRA? e.g. do you run shell scripts as a part of the process to set env values?
Thanks!
@timworx We use Circleci as a CI for testing, deployment on feature, staging and production servers. A common use-case for stage based variables is API endpoint (staging.xyz.com for staging deployment, feature.xyz, and so on), another use-case is managing AWS tokens between different deployment targets.
Now lets say you have a script that sends your build files to an S3 bucket, your generic deployment script(deploy.sh) would have something like
npm run build
aws s3 sync ./build/ $TARGET_BUCKET --delete
and in js code something like this
const apiBaseURL = process.env.REACT_APP_API_ENDPOINT;
In our ci setup it is convenient to set environment variables in a configuration file or in web interface or in a post request as parameterized build. But if I were to run a setup script based on different stages before running deploy.sh I would do
export AWS_ACCESS_KEY_ID="XXXXXX"
export AWS_ACCESS_SECRET_KEY="XXXXXX"
export REACT_APP_API_ENDPOINT="staging.xyz.com"
export REACT_APP_BUILD_ENV="staging"
export TARGET_BUCKET="s3://mywebsite-build/staging/"
This script can be safely kept outside of your code/git history. Also your code does not need stage specific variables as mentioned by bebbi in his last example. This setup also allows deployment anywhere from local machine if you have the right credentials.
I still disagree with hardcoding environment variables like it is done in the line I linked, but to be fair it must have been done to ensure underlying build plugins work well.
OK so this is always handled in CI and out of react app scope.
Thanks for the details @islahul
@islahul
Hi @islahul I need your help to understand the deployment flow you wrote.
I also use scripts to deploy react application to aws S3 so I need to set my env variables before execute the script.
Below code block is your setup script which you said you would use this script to set up env variables. However I just don't understand how to run this script.
export AWS_ACCESS_KEY_ID="XXXXXX"
export AWS_ACCESS_SECRET_KEY="XXXXXX"
export REACT_APP_API_ENDPOINT="staging.xyz.com"
export REACT_APP_BUILD_ENV="staging"
export TARGET_BUCKET="s3://mywebsite-build/staging/"
Forgive me if it's too easy question. I'm on entry level.
Hi @kimcrab, this code block is a set of shell commands and need to be run in the shell/terminal. It should be run before you run commands like npm run build Once you export a variable, you can access it in the node environment(where your build scripts written using webpack/grunt/gulp run) using process.env. So above scripts will enable you to access variables using process.env.REACT_APP_BUILD_ENV Does this help? Happy to connect outside this issue thread in case you need anything else.
Thanks @islahul, now I totally understand the point.
When I type export AWS_ACCESS_KEY_ID="XXXXXX" in terminal, It is just a variable saved inside my terminal and when I type npm run build, webpack access to this variable!
Very simple but didn't understand before.
I just finished test case and now I know what to do!
Thanks again! You saved my day!
Most helpful comment
Hi @kimcrab, this code block is a set of shell commands and need to be run in the shell/terminal. It should be run before you run commands like
npm run buildOnce you export a variable, you can access it in the node environment(where your build scripts written using webpack/grunt/gulp run) using process.env. So above scripts will enable you to access variables usingprocess.env.REACT_APP_BUILD_ENVDoes this help? Happy to connect outside this issue thread in case you need anything else.