Can't access gatsby environment variables on the client side
Asked Answered
I

7

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
Incorruption answered 12/12, 2018 at 11:6 Comment(0)
N
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

Nitrate answered 12/12, 2018 at 14:29 Comment(10)
The empty object screwed me up royally, for hoursFarfamed
I am using .env.*, but when I don't prefix with GATSBY_ the vars are undefined.Bosh
@Bosh 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"Nitrate
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?Debus
You are wrong! Read the docs gatsbyjs.org/docs/environment-variables, variables in .env files should be prefixed with GATSBY_ for getting access to them in JS code (in browser)Chromaticness
@Chromaticness good point mate, when you see something wrong please amend the answer as well, thanks!Ponderable
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..Benumb
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://mcmap.net/q/472319/-webpack-react-process-env-always-empty-windows-10Underexpose
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" })Tinner
ugh, this isn't specified in the documentation, but you also can't destructure process.env like you usually can because of their webpack setupTwenty
P
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.

Pesthole answered 12/7, 2020 at 12:17 Comment(1)
In my case I had to use this code.Pentimento
W
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

Wetmore answered 8/8, 2019 at 9:10 Comment(0)
U
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.

Underexpose answered 29/9, 2020 at 16:53 Comment(1)
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.Neuropathy
T
0

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

{ 
  resolve: `gatsby-plugin-env-variables`,
    options: {
      allowList: [
        "XXXXXXXXX", 
      ]
    }
}
Tresatrescha answered 30/11, 2020 at 11:31 Comment(1)
This doens't do a lot except remove the exception on GATSBY_ naming convention (meh)Peat
S
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}` })
Stylet answered 28/8, 2022 at 9:36 Comment(0)
D
-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',
})
Droit answered 20/5, 2021 at 18:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.