When you don?t have a server-side programming background, environment variables can seem like a bit of magic. That lack of knowledge smacks you in the face like a bag of dicks when you?re done creating todo applications on your localhost, and try to create a production build for the first time.
The problem we?re solving:
How to declare different API url?s for your local development build and production build
In short: environment variables
When working with React, environment variables are variables that are available through a global process.env Object. That global Object is provided by your environment through NodeJs. And because we don?t have NodeJs in the browser, we?re going to need webpack.
Actually setting and using the environment variables
I?m going to show you two ways to set and use environment variables for your React projects with webpack: using npm scripts and using an .env file. I?m going to make the dangerous assumption that you have your React setup stuff in order here.
Method 1: Using npm scripts to set environment variables
First, get webpack and webpack-cli from npm :$ npm install –save-dev webpack webpack-cli.
Go to your package.json, check the scripts key and look for the command(s) that run webpack. It?ll probably look something similar like this:
The double dashed commands are webpack cli commands
Let?s add some environment variables with a –env flag in our scripts.
Notice the –env flag in both scripts
We?ve added the –env.API_URL= part in both scripts. Now, run your npm run dev command, go to your React component and use the process.env.API_URL:
const App = () => <h2>{process.env.API_URL}</h2>;
Aaaand.. I broke your project. Sorry about that.
? That?s because when we use environment variables in our front-end code, they really just serve as placeholders that will be replaced when we compile our code. The problem is, we didn?t tell webpack to compile those variables to real values. Let?s do that in our webpack config file with the DefinePlugin webpack plugin:
DefinePlugin needs you to literally define your ?environment variables? by setting a hard key
You can also reduce the values to a nice object, so you won?t have to define them manually:
When you run your command now, everything gets compiled and your process.env.API_URL will be compiled to the correct url, based on your environment variable.
Congratulations! But wait, there?s more!
Method 2: Using an .env file to set environment variables
The whole idea here is to create a file (called just .env) filled with your environment variables.
To prevent people from finding out your local database password is the same one you use for every single one of your accounts on the internet , I urge you to add the .env file to your .gitignore.
Your front-end code will refer to the same environment variable (process.env.API_URL) on both environments (development/production), but because you defined different values in your .env files, the compiled values will be different.
Let?s create an .env file
This file should exist in the root of your project and is called .env. Let?s add a variable:
API_URL=http://localhost:8000
Is that is? Yes, that?s it..
Handle the .env file
Now we need some way to actually handle the files and its content. We?re going to use a populair npm package called dotenv for this. Dotenv is commonly used (create-react-app uses it, so there) and will get the variables from our .env file and add them to the global process.env.
$ npm install –save-dev dotenv
Adding the variables to your React project
Yeah, that?s great and all. But there?s one problem. Dotenv only works server-side. And we?re not doing back-end stuff.
In this case, we?re developing client-side. And dotenv needs some sort of environment to actually store the variables. Webpack to the rescue!
That whole webpackDefinePlugin stuff was working pretty well earlier, so let?s use it again in our webpack configuration:
Check the dotenv github for configuration options in .config()
Calling .config() on dotenv will return an Object with all the environment variables set in your .env file under a key called parsed. Now, let?s check our React code:
const App = () => <h2>{process.env.API_URL}</h2>;
And damn, it works! It shows the value of the API_URL environment variable that you defined in your .env file.
Just one problem: we still need to define different API_URL values for our production and development environment.
Different environment variables for different environments
The whole idea is to create different .env files for different environments and let webpack pick the correct .env file based on the active environment. So create two files in the root of your project:
- .env (contains all the environment variables for production)
- .env.development (contains all the environment variables for development)
Just to be clear: we?re postfixing the .env filename with the name of the environment. It?s common practice to use the original .env file for your production build, so we won?t be postfixing that one.
Setting the active environment using NPM scripts
We?re going to use NPM scripts (like we did in method 1) to set the current environment in our package.json:
Because we?ve defined our environment in our package.json, we now have it available in our webpack configuration!
The next step is to go to our webpack configuration and let it use the .env file that belongs to our active environment. Just like before, we?re using dotenv, but now we?re specifying a custom path in the parameters:
Getting a bit convoluted there m8
That?s all we?re doing for now, but you could create more .env files for more environments (.env.staging for example), as long as you set the environment in the package.json and create the corresponding .env file in the root of your project!
This last part may be a lot to take in, so go through it line by line and if you have any questions, just comment down below, or on Twitter.
And that wraps it up! You?ve done it!
Great job.
XOXO.