If you are using Create-React-App to scaffold your react application there is built in support for changing environment variables based on the NODE_ENV values, this is done by using .env files. In short this process works by having a .env, .env.production, .env.development set of files. When you run/build your application CRA will set the NODE_ENV value to either development
or production
and based on these values the correct .env file will be used.
This works great, when you have a simple deploy setup. But many times in enterprise level applications you need support for more than just 2 environments, many times it is 3-4 environments. Common logic would suggest that you can accomplish this via the built in mechanism by having additional .env files and changing the NODE_ENV value to the value you care about. However, CRA does not support this with doing an eject
, which will eject all the default conventions and leave it to you to configure your React application. Maybe this is a good idea, but in my case ejecting was not something I wanted to do.
Because I did not want to do an eject
I needed to find another solution, and after a fair amount of searching I found a solution that seems to work for me and my needs and is about the amount of effort as I wanted 🙂
Background:
For my projects needs I needed to support 4 total environments, local, test, non-production, production. I needed to be able to build and deploy to test, non-prod, and prod via our CI/CD pipeline. This means that we could not manually make changes.
Solution:
I found a npm package called react-app-env (repo). This package will take care of changing the config file I want to use based on my build targets. Please note that this does NOT change the NODE_ENV value, just which config file to merge.
My setup I created the following files
- .env (do not commit this to source)
- .env.template (this is not used in the build pipelines, this is for guidance and documentation)
- .env.development
- .env.test
- .env.nonprod
- .env.prod
Now that I have my files setup I need to get the values from the right file into my build.
If I run npm start
from the command line the values in my .env and .env.development files will be used because of the way CRA works. This solution works in development/local mode because I am not worried about packaging and deploying my code.
In order to get my package build correctly for deployment I want to make sure my correct .env.* file is used. To do this I want to make changes to my package.json file in the scripts section.
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "build-prod": "node -r dotenv/config ./node_modules/.bin/react-scripts build dotenv_config_path=.env.prod", "build-nonprod": "node -r dotenv/config ./node_modules/.bin/react-scripts build dotenv_config_path=.env.nonprod", "build-test": "node -r dotenv/config ./node_modules/.bin/react-scripts build dotenv_config_path=.env.test", },
Now that I have my package.json file updated I can build my code and based on the script I run the correct .env.* values will be packaged. The magic above is the way we configure our build-* commands by changing the dotenv_config_path values to be the correct file.
npm run build-prod
npm run build-nonprod
npm run build-test
To verify that my correct values are used I can open up the .js file in the ./build/static/js file and search for my changes.
There may be other ways to solve this same problem, but this works for my needs and is about as simple as I wanted.
Till next time,
Pingback: Interesting links of the week (04/09 – 04/15, 2018) – same stuff, different day