Hey.
How do you deal with environment variables in your Front-end (say React) Application?
But before that, let me give a gist about what it is.
What is Environment Variables?
It is a convention to store all the sensitive information that you deal with in your application (e.g., API Keys, DB URLs, API URLs etc.,) and wrap it in a .env
file.
Let's face it. Most of us don't get to do this setup because it turns out you enter into a project whose Project Scaffolding has already been done.
Perhaps, what if you get to be the initial member of a new project and things go over your head while setting up an application from scratch. That's where we configure environment variable setup initially.
Do you ask me is there only a single way to do that. My answer will be an obvious no.
But wait. There is a way which could actually make your way of dealing with environment variables easier.
“Talk is cheap. Show me the code.” ― Linus Torvalds
How to use .env
.env
file is not going to be a part of your Git Repo as all the files starting with .env is ignored to be pushed by .gitignore
file.
Project Example
Let's look at a very basic React Application Folder Structure using CRA Template.
After clearing out the boilerplate code, this is how my App.js
looks like now:
import "./App.css";
function App() {
return (
<div className="App">
<h1>Hello There. </h1>
</div>
);
}
export default App;
I've changed my .gitignore
slightly
from this :
.env.local
.env.development.local
.env.test.local
.env.production.local
to this :
.env*
just to make sure all the files that has .env
is ignored.
Lets look at the normal use of .env
file first.
.env
configuration
- Add a simple
.env
file into your root directory of the application and write a couple of variables there like below.
REACT_APP_USERNAME = MARK ZUCKERBERG
REACT_APP_EMAIL_ID = MARK@META.COM
REACT_APP_API_KEY = sdklfjhkqhqoiweipjafklnlaksddlkkaskdj
Making use of variables in the project.
Import these variables into a file or a folder inside src
. I've made a properties.js
file in my src
and it looks like this.
export const properties = {
userName: process.env.REACT_APP_USERNAME,
email: process.env.REACT_APP_EMAIL_ID,
apiKey: process.env.REACT_APP_API_KEY,
};
Use it in your App
:
import "./App.css";
import { properties } from "./properties";
function App() {
const { userName, email, apiKey } = properties;
return (
<div className="App">
<h1>Hello There. </h1>
<p>{`I am ${userName}`}</p>
<p>{`My Email ID is : ${email}`}</p>
<p>{`Take this API key to make a call : ${apiKey}`}</p>
</div>
);
}
export default App;
Note : Restart your app after doing this setup as everytime you make changes in .env
file you need to restart your server.
Initial Output
After the development when you actually make the build
folder, the variables gets bundled and when you push the code to your Repo, the .env
would be ignored, so the variables stays within your local Repository.
But is the issue solved yet?
What else to do?
The actual problem with environment variables
Lets say you are working in a production level Application and you have different sets of data for Development, Acceptance and Production.
And for each of those Environments, you might need different API keys or entirely different APIs as well.
How do you differentiate or prioritize which key to use without any hassle in your code setup.
The steps to do this :
- Delete the initially created
.env
file from the root directory. - Download the env-cmd package using
npm install env-cmd
command. - Create a file
.env-cmdrc.json
file in your root directory.
.env-cmdrc.json
looks like this:
{
"dev": {
"REACT_APP_USERNAME": "MARK ZUCKERBERG from dev",
"REACT_APP_EMAIL_ID": "MARK@META-DEV.COM",
"REACT_APP_API_KEY": "sdklfjhkqhqoiweipjafklnlaksddlkkaskdj-dev-api"
},
"acceptance": {
"REACT_APP_USERNAME": "MARK ZUCKERBERG from Acceptance",
"REACT_APP_EMAIL_ID": "MARK@META-ACCEPTANCE.COM",
"REACT_APP_API_KEY": "sdklfjhkqhqoiweipjafklnlaksddlkkaskdj-acceptance-api"
},
"production": {
"REACT_APP_USERNAME": "MARK ZUCKERBERG from Production",
"REACT_APP_EMAIL_ID": "MARK@META-PRODUCTION.COM",
"REACT_APP_API_KEY": "sdklfjhkqhqoiweipjafklnlaksddlkkaskdj-production-api"
}
}
The keys dev
, acceptance
and production
are totally your choice to name them accordingly. Each of those objects denote different environments.
So technically we have setup the configuration for these three servers.
But how do we know which environment we need to access when, because if you recall our properties.js
file has only the variable names mentioned. Nothing about which environment to access from was mentioned.
That's where we use the env-cmd
package we installed.
Let's make a small change in scripts part of the package.json
file to distinguish between the environments which we want to work on.
"scripts": {
"start-dev": "env-cmd -e dev react-scripts start",
"start-acc": "env-cmd -e acceptance react-scripts start",
"start-prod": "env-cmd -e production react-scripts start",
"build-dev": "env-cmd -e dev react-scripts build",
"build-acc": "env-cmd -e acceptance react-scripts build",
"build-prod": "env-cmd -e production react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
What are these now?
Lets break down start-dev
script.
Previously it used to be just start
so that you could do npm start
to do the development in your local.
Now that we have different environments setup, we might need to work on one at a time to test everything is going correct or not.
"start-dev": "env-cmd -e dev react-scripts start"
means,
start-dev
: your actual script to run in the terminal.
It uses env-cmd
package
-e
: you are going to specify the environment.
dev
: This is the environment name that you actually used in .envcmdrc.json
file.
react-scripts start
: default starting script.
That means your are running your application in your local with environment variables of dev server.
This way it is self-explanatory what the remaining scripts do.
That's it. Now you don't need to maintain multiple .env
files to select your environment variables.
The output for dev
when you run the respective script will be:
Similarly for Acceptance
And Production
Bam!!! That's it folks.
If you are here yet, make sure you leave a comment below if you liked or you got any feedback for my writing. Will appreciate that.
Thank you for the read. 😊