Gatsby, Environment variables not accessible in browser

Viewed 2907

I want to use environment variables. I created .env.development file and I put some variables. Then I include the dotenv plugin to read the variables in gatsby-config.js:

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

The content of my .env.development:

GATSBY_APP=MYAPP

It's working in gatbsy-node.js but in browser (REACT) it's empty. I display console.log(process.env) and it return empty object.

Even if I install and configure gatsby-plugin-env-variables.

4 Answers

It looks like you're combining two approaches, and that might be where you're running into trouble.

  1. Gatsby comes out-of-the-box with support for defining environment variables in environment-specific .env.[environment] files (e.g. .env.development), provided these files are in the root of your project (i.e. your-project/.env.development). Documentation for this feature. You do not need to install or configure dotenv for this to work.

  2. Another approach is to use dotenv, which will allows you to use a general .env file. You need to then import and configure the tool, which is generally done at the very top line of gatsby-config.js and looks like this:

     require("dotenv").config()
    

Note that you do not specify the environment name (e.g. development) in this scenario, and you would not commit the .env file to your repository.

The other issue you might run into is that part of your code runs server-side, using Node, and part runs client-side (in the browser). Since process.env is only available in Node, Gatsby does some additional work to make it available in the browser. We don't want all of these variables, which frequently hold secrets, to be provided to the browser, though, so Gatsby only copies over those that whose names begin with GATSBY_. Finally, as a side effect of the way that these variables get copied over, you must explicitly reference them for your build to work:

// this is okay everywhere
const GATSBY_APP = process.env.GATSBY_APP

// this won't work in code that runs client-side, but will work
// in `gatsby-node.js` and other files that only run in Node
const { GATSBY_APP } = process.env

If you wanted to whitelist your own environment variables, either as a prefix (shown here) or have a list of them, you can add something like this in the gatsby-node.js file:

exports.onCreateWebpackConfig = ({ actions, getConfig }) => {
    const config = getConfig();

    // Allow process.env.MY_WHITELIST_PREFIX_* environment variables
    const definePlugin = config.plugins.find(p => p.definitions);
    for (const [k, v] of Object.entries(process.env)) {
        if (k.startsWith("MY_WHITELIST_PREFIX_")) {
            definePlugin.definitions[`process.env.${k}`] = JSON.stringify(v);
        }
    }

    actions.replaceWebpackConfig(config);
};

I was running into the same issue and just found out what I was doing wrong. It looks like you're doing the same thing.

The explanation both the documentation and @coreyward give are correct, however, note that while corey implies they're two different approaches and the issue might be that they're conflicting, they're not, they do different things - so that code of yours is fine.

What's wrong, though, is that you're console logging process.env. And as it turns out, this will always output an empty object even though the variables might be there.

You have to console.log(process.env.GATSBY_APP) directly to see any value. (Reference)

This is essentially an extension of what Corey pointed out in his "finally as a side-effect" section, however, the way he's written it implies it's an issue with destructuring - but it's not limited to that.

In my case, I was doing the above error AND not exposing the variables with GATSBY_ properly, then while testing I started logging the whole env object like you while I searched for the cause. This meant that even after I added the correct GATSBY_ prefix I still couldn't see anything.

So in short, it's probably only your console.log line that's an issue - access the variable directly, not the env object as a whole.

The Gatsby site as a well documented section on working with environment variables. The gist is that the environment variables are only available during build time when the internal nodejs server is server rendering your site. In order, get those environment variables in the browser you need to programmatically embed them using the special gatsby-*.js files. The example they provide seems to be close to what you want to achieve.

Related