30

I set up .env file and gatsby-config.js as below.

// .env.development
GATSBY_API_URL=https://example.com/api
// gatsby-config.js
console.log(process.env)
...
...

Although when to run gatsby develop, it shows all env vars including GATSBY_API_URL: 'https://example.com/api', but there is no env vars on a browser.

// client side
console.log(process.env)  // => this will return {}  empty object

I think I followed https://www.gatsbyjs.org/docs/environment-variables/ as it says, and added GATSBY_ prefix to the var.

Is there a reason why I don't see the env var on the client side?

gatsby info --clipboard

  System:
    OS: macOS Sierra 10.12.6
    CPU: (4) x64 Intel(R) Core(TM) i5-4258U CPU @ 2.40GHz
    Shell: 5.2 - /bin/zsh
  Binaries:
    Node: 11.2.0 - /usr/local/bin/node
    Yarn: 1.9.4 - /usr/local/bin/yarn
    npm: 6.4.1 - /usr/local/bin/npm
  Browsers:
    Chrome: 70.0.3538.110
    Firefox: 63.0.3
    Safari: 12.0.2
  npmPackages:
    gatsby: ^2.0.61 => 2.0.61
    gatsby-image: ^2.0.22 => 2.0.22
    gatsby-plugin-google-analytics: ^2.0.8 => 2.0.8
    gatsby-plugin-manifest: ^2.0.11 => 2.0.11
    gatsby-plugin-no-sourcemaps: ^2.0.1 => 2.0.1
    gatsby-plugin-nprogress: ^2.0.7 => 2.0.7
    gatsby-plugin-react-helmet: ^3.0.4 => 3.0.4
    gatsby-plugin-sass: ^2.0.5 => 2.0.5
    gatsby-plugin-sharp: ^2.0.14 => 2.0.14
    gatsby-plugin-styled-components: ^3.0.4 => 3.0.4
    gatsby-plugin-typescript: ^2.0.2 => 2.0.2
    gatsby-plugin-typography: ^2.2.2 => 2.2.2
    gatsby-plugin-webpack-bundle-analyzer: ^1.0.3 => 1.0.3
    gatsby-source-filesystem: ^2.0.10 => 2.0.10
    gatsby-transformer-sharp: ^2.1.9 => 2.1.9
    gatsby-transformer-yaml: ^2.1.6 => 2.1.6
  npmGlobalPackages:
    gatsby-cli: 2.4.5
kukrt
  • 2,117
  • 3
  • 21
  • 32

7 Answers7

44

A few steps & notes that should solve your problem:

console.log(process.env) will always print empty object

To see if it's really working, you should print the variables directly, e.g. console.log(process.env.API_URL).

Make sure .env.* is in your root folder

In other words, your folder hierarchy should look something like:

.env.development
.env.production
src/
  pages/
    index.js

You don't need to prefix with GATSBY_ if you want to access env variables server-side

From the docs:

In addition to these Project Environment Variables defined in .env.* files, you could also define OS Env Vars. OS Env Vars which are prefixed with GATSBY_ will become available in browser JavaScript.

You need the GATSBY_* prefix if you are using them browser-side

The prefixing is only if you use the OS Env Vars approach (i.e. you set them directly on your server and not in these .env files).

Kill and restart gatsby develop when you've added the .env file(s)

I ran into this when reproducing on CodeSandbox (in CodeSandbox, you do the restart by going to Server Control Panel on the left, and clicking Restart Sandbox).

Here's the working example: https://codesandbox.io/s/jj8xzn2y15

Mel Macaluso
  • 3,250
  • 2
  • 12
  • 26
Tadas Antanavicius
  • 4,882
  • 1
  • 20
  • 20
  • 16
    The empty object screwed me up royally, for hours – Jeff Lau Mar 06 '19 at 02:34
  • 2
    I am using .env.*, but when I don't prefix with `GATSBY_` the vars are `undefined`. – Jim Sep 02 '19 at 00:01
  • @Jim did you see the additional answer below? "Maybe worth noting that it's easy to misname the file if you are used to writing .dev or .develop. Gatsby requires that the file is named exactly: .env.development" – Tadas Antanavicius Sep 03 '19 at 12:45
  • Damn, I was printing `process.env` the whole time and an empty object was being printed. Why exactly won't it print all of its properties at the exact moment of the `console.log`? – Guilherme Matuella Sep 11 '19 at 19:39
  • 2
    You are wrong! Read the docs https://www.gatsbyjs.org/docs/environment-variables/, variables in .env files should be prefixed with GATSBY_ for getting access to them in JS code (in browser) – Skiminock Sep 23 '19 at 14:02
  • @Skiminock good point mate, when you see something wrong please amend the answer as well, thanks! – Mel Macaluso Oct 17 '19 at 10:09
  • What's not clear to me in the Gatsby Docs is the difference between Project vars and OS vars. What is an OS var? It's not explained in the docs. Then, there's when to use 'GATSBY_' prefix or not. Does that prefix only apply to development environments, OS vars? Still confused.. – David Gaskin Jun 05 '20 at 17:27
  • 3
    Here's an explanation of why `process.env` object is empty. Basically Gatsby employs Webpack's DefinePlugin which replaces occurrences of `process.env.YOUR_VARIABLE` during build time, it does not expose `process.env` per se. https://stackoverflow.com/a/41248996/2579733 – Max Ivanov Sep 29 '20 at 13:14
  • 2
    If you try to change the naming convention by using something like this, it will not work (stick to gatsby naming convention): `require('dotenv').config({ path: ".env" })` – zakum1 Feb 26 '21 at 00:48
  • ugh, this isn't specified in the documentation, but you also can't destructure `process.env` like you usually can because of their webpack setup – Haroen Viaene Nov 28 '22 at 09:18
17

Make sure you've included

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

in your gatsby-config.js file before you start using your ENV variables.

ᴍᴇʜᴏᴠ
  • 4,804
  • 4
  • 44
  • 57
Aistis Gasparo
  • 171
  • 1
  • 4
14

Maybe worth noting that it's easy to misname the file if you are used to writing .dev or .develop.

Gatsby requires that the file is named exactly: .env.development

Soft Bullets
  • 4,425
  • 2
  • 18
  • 15
4

In Gatsby, availability of your environment variables depends on many factors:

  • Execution context. Are you trying to reach the variable client-side or server-side?
  • Variable name. Names starting with GATSBY_ are treated differently.
  • Environment file name. By default, Gatsby expects these to be .env.production and .env.development.
  • DotEnv usage. Whether you're using dotenv npm package to load the env file.

Here are the different ways to make an environment variable accessible in server and browser environments. Choose whichever fits your setup best.

Server-side:

1. Define an OS environment variable.

MY_VAR='my value'; export MY_VAR // will persist in the OS environment
npm run start

OR

MY_VAR='my value' npm run start // will set the variable for that process only

Note: variable name doesn't matter.

2. Create an env file and define variable there.

echo MY_VAR='my value' >> .env.development

Load the file in gatsby-config.js:

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

Note: file name doesn't matter. Variable name doesn't matter.

Client-side:

1. Create a .env.development (.env.production for prod environment) file and define a variable there.

Note: file name does matter. Variable name doesn't matter.

2. Create an environment file named differently (say .env) and define a GATSBY_ prefixed variable there.

echo GATSBY_MY_VAR='my value' >> .env

Load the file in gatsby-config.js with dotenv.

require('dotenv').config() // .env is loaded by default, no need to specify path

Note: file name does not matter. Variable name does matter.

3. Define a GATSBY_ prefixed OS environment variable.

GATSBY_MY_VAR='my value'; export GATSBY_MY_VAR
npm run start

OR

GATSBY_MY_VAR='my value' npm run start

Note: variable name does matter.

Max Ivanov
  • 5,695
  • 38
  • 52
  • How can we use the GATSBY_ prefixed OS environment variable in client javascript during build command? I ran - 'GATSBY_SOME_TOKEN=12345 npm run build'. I tried to use process.env.GATSBY_SOME_TOKEN but i was not able to access the value in my component file. I was able to access the value in gatsby-config. Please tell me a way to access GATSBY_SOME_TOKEN value in component file during the build command. – Harsh Gupta Jul 01 '21 at 19:33
0

you may add your env key to the allow list in gatsby-config.js

{ 
  resolve: `gatsby-plugin-env-variables`,
    options: {
      allowList: [
        "XXXXXXXXX", 
      ]
    }
}
msahin
  • 1,520
  • 1
  • 16
  • 22
  • This doens't do a lot except remove the exception on `GATSBY_` naming convention (meh) – Liam Feb 16 '22 at 17:18
0

Check the official doc.

Gatsby requires that we use the name of the file as .env.development and .env.production for development and production respectively.

And in the gatsby-config.js,

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

If you use typescript (i.e. gatsby-config.ts),

import * as dotenv from 'dotenv'
dotenv.config({ path: __dirname + `/.env.${process.env.NODE_ENV}` })
Anh-Thi DINH
  • 1,845
  • 1
  • 23
  • 17
-1

If you plan on using a single .env file (not something like .env.development and .env.production) then adding this to gatsby-config.js should do the trick:

require('dotenv').config({
  path: '.env',
})
Félix Paradis
  • 5,165
  • 6
  • 40
  • 49