How to implement '.env' variables in Gatsby and React 
Tags: react, gatsby, dotenv
Published: 2021-04-15 08:10:32

For a recent project we were struggling to get the '.env' variables into our public documents. As for security we should keep sensitive information away from daylight. That’s why it’s important to work with these environmental variables. Some might have found the same difficulties, but when working with frameworks I experienced there are some extra conditions you have to pay attention to.

For our project I started out with a MERN project, my teammate started to research Gatsby and Cloudinary and started out there. Since Gatsby is based on React we figured there wouldn’t be compatibility issues. Yet we found out by experience of combining our work into one project folder, each framework works with a different set of rules regarding the use of '.env' variables. For implementing my files in the Gatsby project I had to research the differences. This article highlights the differences in implementation of these variables in the Gatsby and React frameworks.

# Implementing environmental variables in you project

For starters: this is a universal instruction. Go to the root of your project in your *terminal* (where the 'package.json' file is stashed). Normally there should be a 'package.json' already, else you need to make one first.
To use this dependency you need to install the [dotenv package](https://www.npmjs.com/package/dotenv). I mainly work with npm package manager but you can also install this package with yarn:

```terminal
npm i dotenv
or
yarn add dotenv
```

Now the dotenv module is added to your dependencies in the 'package.json' file.

## [React](https://create-react-app.dev/docs/adding-custom-environment-variables)

To define your environmental variables you basically just need a '.env' file, but if you're working with different environments you can add specifications to the filename (see official docs of React; link in title).

```terminal
touch .env
```

There  you can start adding your sensitive information in variables. It is necessary you start with REACT_APP_ before the variable name, otherwise the variables won't be read.

```dotenv
//.env

REACT_APP_ATLAS_DB_NAME=string

```

To use '.env' in your React project you have to paste this code at the top of each file where you want to use an environmental variable:

```javascript
// index.js
/* CommonJS */
require('dotenv').config();

/* ES6 Modules */
import dotenv from 'dotenv';
dotenv.config({path: '/server/.env'});

// package.json
/* CommonJS */
...
"type": "commonjs",
...
/* ES6 Modules */
...
"type": "module",
...
```

## [Gatsby](https://www.gatsbyjs.com/docs/how-to/local-development/environment-variables/)

In Gatsby you cannot work with a plain '.env' file but only with '.env.development' or '.env.production'.

Depending on the cli command the needed '.env' file will be processed when hosting:
+ **Development**

  If you run 'gatsby develop', then you will be in the development environment.
+ **Production**

  If you run 'gatsby build' or 'gatsby serve', then you will be in the production environment.

You can put your environmental variables in either a '.env.development' or '.env.production' file, it's recommended to start with the development and change this file to a production type:

```terminal
touch .env.development
or
touch .env.production
```
In this case it is necessary you start with GATSBY_ before the variable name, as it is the same for when using only React: the variables won't be read otherwise.

```dotenv
//.env.development

GATSBY_ATLAS_DB_NAME=string

```

To use '.env' in your gatsby project you have to paste this code at the top of your gatsby-config.js file:

```javascript
// gatsby-config.js

require("dotenv").config({
  path: `.env.${process.env.NODE_ENV}`,
});
```

So Gatsby doesn’t per se work with the strict ES6 module type (but it is possible with the [esm plugin](https://support.gatsbyjs.com/hc/en-us/articles/1500000294121-Using-ES6-Module-Syntax-in-Gatsby-API-Files-on-Gatsby-Cloud)). The gatsby-config.js doesn't allow import syntax, only the require.
There's no need to add - "type": "module" - to the 'package.json' file.

## Using the variables in your public files

Now you can retrieve this value in your server and client side (pages, components) by starting with 'process.env.' and adding the variable name:

```javascript
// Example gatsby-config.js

resolve: 'gatsby-source-mongodb',
options: {
    // Name of the database and collection where are books reside
    dbName: process.env.GATSBY_ATLAS_DB_NAME,
    ...
}

// Example src/pages/index.js (Gatsby) src/index.js (React)
render() {
  return (
    <div>
        <img src={`${process.env.GATSBY_API_URL}/logo.png`} alt="Logo" />
      OR
        <img src={`${process.env.REACT_APP_API_URL}/logo.png`} alt="Logo" />
    </div>
  )
}
```

When working in React chances are you're working with a server and client folder. I didn't manage to use the '.env' file from server to client by path. An experienced developer I know said he uses a file per folder. I'm still hoping to get this done by using the path option in the config function (config({path: '/path/.env})), but the documentation I have found so far hasn't provided me with the solution.

If you know advice on this you can always help me by commenting on this article!

And never forget: when you deploy your files on GitHub, make sure your '.env' files are listed in the '.gitignore' file you put at the root of the project and you'll serve the purpose of this set-up.