nico.fyi
Published on

[Dev Note] Using Environment Variables in NextJS Safely and Conveniently

Authors
  • avatar
    Name
    Nico Prananta
    Twitter
    @2co_p

UPDATE May 11, 2020

As of version 9.4, NextJS finally has proper environment variables support. Simply put the variables in .env file:

  • Environment variables are only available in the Node.js environment by default.
  • Environment variables prefixed with NEXTPUBLIC are exposed to the browser.

Problem

I really like nextjs. But their recommendation to add environment variable to the Javascript bundle is not appropriate in my opinion. According to the documentation, you need to add the environment variables in the next.config.js file.

module.exports = {
  env: {
    customKey: 'my-value',
  },
}

However, this next.config.js file is usually commited to the project's repository. So if some of the environment variables are sensitive information (e.g., API keys), that information could leak to public.

Solution #1

If you use Vercel to host your app, you can add environment variables from the Project Settings in vercel dashboard. Environment Variables are accessible during both Build Step and Runtime, and can be configured for Production, Preview, and Development Environments individually.

Once you add your environment variables to Vercel, you need to add the name of the environment variables to next.config.js file:

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

Solution #2

The most popular way to use environment variables is using dotenv. To use dotenv in nextjs app, first install it

# with npm
npm install dotenv

# or with Yarn
yarn add dotenv

Then define the environment variables in .env file in the root directory of the project. Usually, you can ignore this file in your repository.

SECRET_SOMETHING=XXXXXX

Then expose it to your nextjs app in next.config.js file,

require('dotenv').config()

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

But adding the variables one by one is such a chore. So I wrote this small function to filter environment variables with certain prefixes.

// next.config.js file
require('dotenv').config()

const getEnvWithPrefixes = (prefixes = ['REACT_APP_', 'FIREBASE_']) => {
  return Object.keys(process.env).reduce((prev, curr) => {
    if (prefixes.some((p) => curr.startsWith(p))) {
      return {
        ...prev,
        [curr]: process.env[curr],
      }
    }

    return prev
  }, {})
}

module.exports = {
  env: getEnvWithPrefixes(),
}

Using this getEnvWithPrefixes function, you need to define your environment variables' names with certain prefixes. In the above example, the names can be prefixed with either REACT_APP_ or FIREBASE_ like the following:

REACT_APP_SECRET=XXXXXX
FIREBASE_KEYS=XXXXXX

We use prefixes to prevent unrelated environment variables from leaking to your project. This way, we don't need to update next.config.js whenever we add a new environment variable to .env file.