nico.fyi
    Published on

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

    A developer's guide on using environment variables in NextJS effectively, updated for version 9.4.

    Authors

    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.