DEV Community

Cover image for Environment Variables in Next.js
Akhila Ariyachandra
Akhila Ariyachandra

Posted on • Updated on • Originally published at akhilaariyachandra.com

Environment Variables in Next.js

Updated my original blog post on 18th May, 2020 to reflect the how Next.js v9.4+ handles the .env file.

Often we need to use certain variables like the database path or authentication secrets without committing them to the repo.

Since Next.js uses Webpack we can use the dotenv-webpack dependency to load variable from a .env file to our Next.js application.

Let's start by installing dotenv-webpack as a dev dependency.

npm install dotenv-webpack -D
Enter fullscreen mode Exit fullscreen mode

Next we need to modify the Webpack configuration in Next.js. This is done through the next.config.js file.

First import the dotenv-file dependency.

const Dotenv = require("dotenv-webpack");
Enter fullscreen mode Exit fullscreen mode

Next export the config object with the default Webpack config function.

module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {

    return config;
  }
};
Enter fullscreen mode Exit fullscreen mode

All we need to do now is add the dotenv-plugin into the Webpack plugins array.

module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    // Add the new plugin to the existing webpack plugins
    config.plugins.push(new Dotenv({ silent: true }));

    return config;
  }
};
Enter fullscreen mode Exit fullscreen mode

Finally the next.config.js should look like this.

// next.config.js
const Dotenv = require("dotenv-webpack");

module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    // Add the new plugin to the existing webpack plugins
    config.plugins.push(new Dotenv({ silent: true }));

    return config;
  }
};
Enter fullscreen mode Exit fullscreen mode

Now you can use environment variables in the application. For example, if your .env file is like this,

AUTH_SECRET=verysecret
Enter fullscreen mode Exit fullscreen mode

You can use the variable like this, process.env.AUTH_SECRET.

Never commit the .env file. Add it to the .gitignore file.

Deploying to Vercel

If you are using a Git provider like Github to deploy the Application in Vercel, you can't use .env file. This is the reason we set the silent property when adding dotenv-webpack plugin, to prevent any errors because of the missing .env file.

config.plugins.push(new Dotenv({ silent: true }));
Enter fullscreen mode Exit fullscreen mode

Instead of the .env file we will use the Environment Variables UI available in Vercel.

To start, install, log into the Vercel CLI and link it to a project if you haven't already.

npm i -g now
now login
now
Enter fullscreen mode Exit fullscreen mode

Then use the following command to set the Environment Variables in the deployment environment.

now env add
Enter fullscreen mode Exit fullscreen mode

Finally to make the variables available in the client side code, we need to add one more property to the Next.js config. Add a new property called env and list all the environment variables you want in the client side code as follows.

// next.config.js
const Dotenv = require("dotenv-webpack");

module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    // Add the new plugin to the existing webpack plugins
    config.plugins.push(new Dotenv({ silent: true }));

    return config;
  },
  // Have to list all the environment variables used here to make it available
  // to the client side code
  env: {
    AUTH_SECRET: process.env.AUTH_SECRET,
  },
};
Enter fullscreen mode Exit fullscreen mode

This feels like a really hacky workaround to me, so if you have any suggestions on how to improve it please let me know in the comments below.

Wrapping up

You can find an example of the implementation here.

I hope you found this guide helpful. Please be sure to share it and leave a comment below! 😊

Top comments (21)

Collapse
 
erangakapukotuwa profile image
Eranga Lakmal • Edited

Hello Akhila. My name is Eranga from Colombo. I have a question. When we create a secrete using now secrets add. It's available in the Development environment. But how do we publish it to "Preview" and "Production" envoronments of Zeit. I am using Zeit now. The env variable is working fine in the Dev env. But it's undefined in the Prev and Prod envs. Any clue ?

Collapse
 
akhilaariyachandra profile image
Akhila Ariyachandra

ZEIT recently changed recently changed how the Environment Variables are handled, so I'll need to update the post to reflect that. From what I've tested so far, the now.json file and secrets are no longer needed. You just need to specify the variables with now env add. Hope it helps.

Collapse
 
erangakapukotuwa profile image
Eranga Lakmal

Thank you for replying. Yes, It's working without now.json and the secrets. But after we deploy it the values are not available(undefined) in the "Preview" environment.

Thread Thread
 
akhilaariyachandra profile image
Akhila Ariyachandra

Could you go to the project page in Vercel (ZEIT) and check if the variables are available for Preview? If not you can manually added from there.

Screenshot

Thread Thread
 
erangakapukotuwa profile image
Eranga Lakmal

Yes. I have set the values. We can create env values for all the environments locally using the now env add <VARIABLE NAME> command and publish to remote. Also we can add values directly on the settings page and pull them to the local using now pull env. I tried both ways. Unfortunately the values are available in local but not available on Preview in both cases. Bad luck

Thread Thread
 
akhilaariyachandra profile image
Akhila Ariyachandra • Edited

A workaround I found for now is to list all the variables you want in the client side code in the env property of the Next.js config.

env: {
    AUTH_SECRET: process.env.AUTH_SECRET,
}

I updated the post with more details.

Collapse
 
ericwallen profile image
Eric Wallen

Hi, I am having the same problem. This solution is working locally for development but when I deploy to preview or production the values are undefined.

Thanks for helping me get this far. It's nice to have a development working. If you have any idea how to get preview and production to work I would be truly in your debt.

Collapse
 
akhilaariyachandra profile image
Akhila Ariyachandra • Edited

A workaround I found for now is to list all the variables you want in the client side code in the env property of the Next.js config.

env: {
    AUTH_SECRET: process.env.AUTH_SECRET,
}

I updated the post with more details.

Collapse
 
ericwallen profile image
Eric Wallen • Edited

Sweet, thanks. I tried it and it's working. Very helpful.

Collapse
 
alekslario profile image
Aleksandrs Larionovs

Or you can just put all env vars in now.json and not commit it to github. Problem solved?

Collapse
 
akhilaariyachandra profile image
Akhila Ariyachandra

Not really because this won't make environment variables available in the ZEIT deployment environment.

Collapse
 
alekslario profile image
Aleksandrs Larionovs

It will when you deploy with now or now --prod(If you put actual envs not just "@now-auth-secret" references). I mean it works for me, not sure what kind of problems you've encountered

Thread Thread
 
akhilaariyachandra profile image
Akhila Ariyachandra

The purpose of using the .env file is to avoid committing sensitive data like the database URI or the JWT secret to the repo. In an ideal case we should avoid doing it at all costs, but if the variable isn't sensitive we could add it directly to now.json and commit it to the repo (though I still wouldn't recommend it).

Thread Thread
 
alekslario profile image
Aleksandrs Larionovs

Thats what my first comment was about, put envs in now.json and add it to git ignore. It serves the same purpose as .env

Thread Thread
 
tdotholla profile image
Kiel

don't now.json files need to get commited though?
env files never get committed...
there's also a .nowignore file specifically to ignore now stuff.....

Came here because i'm in the same boat trying to "do it right" by using now secret and .env files locally, and the env variables UI at vercel.com.

None are working in preview/prod. only locally in dev.

Thread Thread
 
alekslario profile image
Aleksandrs Larionovs • Edited

If there is no config other than your envs in now.json, there is no need to commit it. Now.json file+Vercel is one of the ways to deploy your nextjs(or other) app, it's not integral part of you repo.

Collapse
 
michael_webdev profile image
Michael B.

Seriously, THANK YOU. I've been struggling the whole day trying to make it works, but the Next.js doc was useless.
Thanks again

Collapse
 
michael_webdev profile image
Michael B.

I talked to fast :p

It works well locally, but as soon as I test it on zeit (vercel), I have undefined on all my variables...

Collapse
 
akhilaariyachandra profile image
Akhila Ariyachandra

Did you upload the variables using now env add. Maybe I'll need to review my post again. I originally wrote it when we had to use Zeit secrets.

Thread Thread
 
michael_webdev profile image
Michael B. • Edited

No but I managed to do something with this repo: github.com/zeit/next.js/tree/canar...

1) Create now.json and fill it like that :

{
  "build": {
    "env": {
      "SECRET": "@my-secret-key",
      "ANOTHER_SECRET": "@my-other-secret-key"
    }
  }
}

2) Then in your next.config.js you'll add module.exports:

module.exports = {
  env: {
    SECRET: process.env.SECRET,
  },
}

3) What worked for me at the end was to add my variables using "now secret add". I previously added my variable in the new variable UI on the website but it didn't work...

Hope this will help!

Thread Thread
 
akhilaariyachandra profile image
Akhila Ariyachandra • Edited

A workaround I found for now is to list all the variables you want in the client side code in the env property of the Next.js config.

env: {
    AUTH_SECRET: process.env.AUTH_SECRET,
}

I updated the post with more details. In the example I linked at the end of the post, I didn't use any secrets.