147

I'm using the following environment variable in my create-react-app:

console.log(process.env.REACT_APP_API_URL) // http://localhost:5555

It works when I run npm start by reading a .env file:

REACT_APP_API_URL=http://localhost:5555

How do I set a different value like http://localhost:1234 when executing a npm run build?

This is my package.json file:

{
  "name": "webapp",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "react-scripts": "0.9.0"
  },
  "dependencies": {
    "react": "^15.4.2",
    "react-dom": "^15.4.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}
VLAZ
  • 26,331
  • 9
  • 49
  • 67
sigmus
  • 2,987
  • 3
  • 23
  • 31

6 Answers6

247

I imagine you got this working by now, but for anyone else that finds this, you set your default environment variables in a .env file at the root of your "create-react-app" project.

To separate out the variables used when using npm start and npm run build you can create two more env files - .env.development and .env.production.

npm start will set REACT_APP_NODE_ENV to development, and so it will automatically use the .env.development file, and npm run build sets REACT_APP_NODE_ENV to production, and so it will automatically use .env.production. Values set in these will override the values in your .env.

If you're working with other people, and have values specific to your machine only, you can override values in .env.development and .env.production by adding those values to a new file - .env.development.local and .env.production.local respectively.

EDIT: I should point out that the environment variables you have set must start with "REACT_APP_", eg. "REACT_APP_MY_ENV_VALUE".

EDIT 2: if you need more than just development, and production, use env-cmd, as specified by this comment.

Baldeep
  • 4,213
  • 4
  • 17
  • 17
  • 2
    @SebastianBean It uses process.env from node: `process.env.REACT_APP_API_URI`. See the [CRA documentation](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-custom-environment-variables) – Adi Unnithan Oct 19 '17 at 18:50
  • If the build script always sets environment ='production'. how do i deploy my environment = 'test' to my testing server ? – caffeinescript Nov 01 '17 at 04:16
  • 2
    @caffeinescript There is currently no way to have any environments other than "development" and "production". A really roundabout workaround I have is to add a script in package.json which sets an environment variable denoting it's testing mode, i.e. `build_testing": "set REACT_APP_ENV=test & react-scripts build`, and then have a settings.js file where each environment variable has it's own function, with an if statement that checks the content of `process.env.REACT_APP_ENV` and either returns a hard-coded value for the test environment, or the real environment variable. – Baldeep Nov 01 '17 at 16:46
  • yeah thanks for the reply @user3255240. thats what i ended up doing. – caffeinescript Nov 02 '17 at 07:38
  • 12
    Thanks for the info on needing to start with REACT_APP_; I ran into an issue with that. – DylanSp Dec 29 '17 at 15:17
  • 2
    Also, don't forget to RESTART the app from TERMINAL. – Animesh Singh Feb 11 '18 at 17:24
  • Please note that you need to restart the server to see the changes in .env file. – phantomCoder Aug 21 '18 at 05:13
  • What is the best approach for example when having a deployed version of the code in a test environment and a different deployed version that actually is the production environment. How can I replicate this with environment variables? – maracuja-juice Oct 27 '18 at 08:29
  • @maracuja-juice If you only have 2 environments, and the only differences are things like how many threads to spin up, or what DB connection string to use. Create a '.env.development' file with your test variables, and a '.env.production' file for your production variables, and then call them in code...see the [documentation](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#adding-development-environment-variables-in-env) for more detail. – Baldeep Nov 05 '18 at 16:32
  • @Baldeep But when npm run build is run then the production variables get used automatically – maracuja-juice Nov 06 '18 at 12:43
  • @maracuja-juice then I would recommend starting your test environment app using 'npm start', or looking into env-cmd – Baldeep Nov 06 '18 at 15:34
  • @Baldeep I don't think Netlify supports this, as you can only use the same build command for production and test. I'll need to look into this. – maracuja-juice Nov 07 '18 at 07:58
  • https://scriptverse.academy/tutorials/reactjs-environment-variables.html -> I found this link that describes this answer in a little more detail + the REACT_APP_ prefix. Hope it helps those who are still figuring out how to do it. – f0rfun Oct 23 '19 at 07:12
  • 1
    https://create-react-app.dev/docs/adding-custom-environment-variables/#adding-development-environment-variables-in-env This documentation also helped add much more detail – Mathyou Feb 04 '21 at 00:45
  • If you are going to use the env-cmd if you want to use more than the development and production .env files, make sure you see the latest update here. You need to use the -f parameter: https://github.com/toddbluhm/env-cmd#using-custom-env-file-path – Jason Washo Jul 18 '23 at 19:25
64

You can use the process.env.NODE_ENV like so:

const apiUrl = process.env.NODE_ENV === 'production' ? process.env.REACT_APP_PROD_API_URL : process.env.REACT_APP_DEV_API_URL;

You would need to have REACT_APP_PROD_API_URL and REACT_APP_DEV_API_URL set.

Or, if the production URL is always the same, you could simplify it:

const apiUrl = process.env.NODE_ENV === 'production' ? 'https://example.com' : process.env.REACT_APP_DEV_API_URL;

Create React App sets the NODE_ENV to 'production' for you on build, so you don't need to worry about when to set it to production.

Note: you must restart your server (e.g. run npm start again) to detect environment variable changes.

dahlbyk
  • 75,175
  • 8
  • 100
  • 122
Andy_D
  • 4,112
  • 27
  • 19
  • Thanks. I'm aware of this approach. Do you think this is the canonical solution for this situation? – sigmus Feb 25 '17 at 20:16
  • 2
    If you do your webpack config "by hand", there would be a bunch of ways to do this. I don't honestly know if it's "canonical", but this way works, and without ejecting from CRA, so I like it. – Andy_D Feb 25 '17 at 20:26
  • 4
    We're also thinking about adding support for environment-specific .env files in the future. – Dan Abramov Feb 26 '17 at 17:57
  • 1
    Thought I might work on this but here it is https://github.com/facebookincubator/create-react-app/pull/1344 – Andy_D Feb 26 '17 at 20:51
  • 3
    Something silly that I was not aware of but hopefully may help other inexperienced developers, environment variables set inside of the `package.json` file need to be defined _before_ the `react-scripts build` command in order to be detected, for example, `REACT_APP_YOUR_VARIABLE=here react-scripts build`. – Andy Sep 08 '17 at 14:19
  • Hate to point this out but maybe I'll save an hour of someone's life. Restart your server to update your env variables – Pip Sep 24 '18 at 06:14
  • This article helped me alot. Thought I'd add it to the commentary here... https://medium.com/@tacomanator/environments-with-create-react-app-7b645312c09d – madeyejm Nov 05 '18 at 22:03
  • Why should you have to run `npm start` if you're running a build? Doesn't make any sense. – AlxVallejo Jan 13 '19 at 21:27
  • Where and how to use latter this `apiUrl` variable. Can you give example how you used it, please. – Predrag Davidovic Sep 21 '20 at 09:58
59

If you'd like to have separate dotenv files for building and/or deploying to separate environments (stage, prod) then you can use env-cmd like so:

npm install --save-dev env-cmd
./node_modules/.bin/env-cmd -f ./stage.env npm build

Then just update your package.json accordingly:

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "build:stage": "env-cmd -f ./.stage.env npm run-script build"
  },

Then to build you'd just run this shell command:

npm run build:stage
chrishiestand
  • 2,800
  • 1
  • 25
  • 25
  • Its helpful to have a link to `env-cmd` here, but IMO it is dangerous to have different builds for different deplozments – helt Jul 03 '19 at 13:55
  • 1
    @helt Could you elaborate? What are the risk factors you're concerned with? – chrishiestand Jul 03 '19 at 17:10
  • 2
    Well, if I bake in the configuration during the build, I have to build the app individually for each deployment/environment. I cant port one build to another environment, which will make things complicated when we dont want it to (Murphys Law). Plus, it's quite an overhead for the CI, if it has to build multiple times only for replacing env vars. Basically, I stumbled over [so thread](https://stackoverflow.com/questions/49975735/rendering-an-environment-variable-to-the-browser-in-a-react-js-redux-production) which is roughly the use case I have. – helt Jul 04 '19 at 11:18
  • 3
    Those are trade-offs to know about for sure. But I don't think they are the most important factors in *every* use case. For some it may be acceptable to have multiple artifacts for each commit. And the alternate solutions have negatives of their own: additional infrastructure requirements (e.g. a node.js server), or significantly slower container startup times. IMO, this is a question of what works best for you. – chrishiestand Jul 05 '19 at 19:23
  • 2
    this is the only feasible solution I can see. I don't understand how (using the default create-react-app environment variables setup) you actually create build files that you could deploy to test or dev. npm run build creates build files for production, but that's it, as far as I can see (what am I missing, I must be missing something?) – blomster Nov 09 '20 at 09:09
  • @blomster, the alternate solutions that I found were: 1. Use an external server/service that your app connects to during runtime, and the server can tell the app which env it's running in. 2. The container contains the src files and public resources, but not the build artifact files. When the container starts, the react/front-end build happens using the appropriate env variables (instead of the react build happening at container build). After the build, the server starts with the correct env vars for that env. – chrishiestand Jul 16 '21 at 17:19
  • You don't even need to update package.json file. Just running env-cmd -f .env.stage yarn build works fine. – Iqbal Nov 19 '21 at 09:51
48

Also, it can be done without additional dependency:

"scripts": {
  "build": "sh -ac '. ./.env.${REACT_APP_ENV}; react-scripts build'",
  "build:staging": "REACT_APP_ENV=staging npm run build",
  "build:production": "REACT_APP_ENV=production npm run build"
},

And have .env.staging, .env.production files accordingly

Artem Matiushenko
  • 814
  • 10
  • 14
  • 1
    Just a pity that it references npm directly. Would be nice if we could capture the binary that called the target in the first place so it also works when called through yarn for instance, that yarn then gets invoked instead of npm run. – Kasper Mar 23 '21 at 12:26
  • 4
    `"build:production": "REACT_APP_ENV=production yarn build"` will work as well – Artem Matiushenko Mar 23 '21 at 13:32
  • Yeah I know, that's what I use :-) But my colleague has to add a different one for npm cause he wants to use npm. Anyway, small issue, might be solvable with a TOOL env param or so. not sure. – Kasper Mar 29 '21 at 09:38
  • How can I get this to work with `craco build`? – Florian Walther Mar 14 '22 at 21:48
  • 1
    I personally didn't try it with craco, but in the theory, it might work the same way. Instead of `react-scripts` you should have `craco`. Try this `"build": "sh -ac '. ./.env.${REACT_APP_ENV}; craco build'"` – Artem Matiushenko Mar 15 '22 at 13:00
  • 1
    in Windows you would need to use `"build:production": "set REACT_APP_ENV=production & npm run build"` – Arno van Oordt Feb 23 '23 at 08:18
18

install 'env-cmd' package

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "deploy": "gh-pages -d build",
    "start:qa": "env-cmd -f .env.qa react-scripts start",
    "build:qa": "env-cmd -f .env.qa react-scripts build"
  },

in local if we want to run qa environment use npm run start:qa

1

If you are using Heroku for deployment, then follow this:

  • Go to your app settings >> click on 'Reveal Config Vars' button
  • Add your variables
  • Use them in the app in the same way as you are using previously ex. process.env.REACT_APP_VARIABLE_NAME
  • Re-Deploy the app and that's it...