How to use different .env files with nextjs?

41,919

Solution 1

Next 9.4 has built-in support for .env files: https://nextjs.org/docs/basic-features/environment-variables

But, in case you want to have multiple .env files, like:

  • .env.development
  • .env.staging
  • .env.prestaging
  • .env.production

It would be impossible to do with a built-in env variables support. There's only 3 environments that officially supported for now, it's: "development", "test", "production". With next dev you use "development", next build && next start uses "production" environment.

If you need to build for production environment, but using ".env.staging" for example, then you need to add env-cmd package, and add this line to your package.json:

"build:staging": "env-cmd -f .env.staging yarn build && yarn start"

Next would make a production build with ".env.staging" variables.

Solution 2

The issue with most of these answers is they go against the principal of "build once run everywhere", in reality most of us are using this technique build and run with Docker containers. It's not possible to have multiple build commands like this, and it would be bad practice.

Better have your environment available at runtime. We created a package that allows next static optimisation and still have runtime env vars via window.__ENV

https://github.com/andrewmclagan/react-env

This works by generating an environment config object at runtime from whitelisted env vars:

{
  ...
  "scripts": {
    "dev": "react-env -- next dev", // where .env.${APP_ENV}
    "start": "react-env --env APP_ENV -- next start" // where .env.${APP_ENV}
  }
  ...
}

Solution 3

You can have different .env files in nextjs with following two ways:

1. Using env-cmd package

Provide the path to your environment file in the scripts like:

"scripts": {
    "start": "env-cmd path/to/prod/env/file next start",
    "start:dev": "env-cmd path/to/prod/env/file next dev",   
    "build:dev": "env-cmd path/to/dev/env/file next build",
    "build:test": "env-cmd path/to/test/env/file next build",
    "build:stage": "env-cmd path/to/stage/env/file next build",
    "build": "env-cmd path/to/stage/prod/file next build",        
},

2. Using dotenv package

In your next.config.js file add following:

require("dotenv").config({ path: `${process.env.ENVIRONMENT}` });

module.exports = {
      // your configs
}

and in your scripts, provide that ENVIRONMENT variable like:

"scripts": {
    "start": "ENVIRONMENT=path/to/prod/env/file next start",
    "start:dev": "ENVIRONMENT=path/to/dev/env/file next dev",
    "build:dev": "ENVIRONMENT=path/to/dev/env/file next build",
    "build:test": "ENVIRONMENT=path/to/test/env/file next build",
    "build:stage": "ENVIRONMENT=path/to/stage/env/file next build",
    "build": "ENVIRONMENT=path/to/stage/prod/file next build",        
},

NOTE: The thing is do not to put your .env* files in the root folder, otherwise NEXT will auto-pick from your .evn* files and it only supports production and development stages. So it'll ignore other .env.my-stage files.

Solution 4

Next 9.4 support out of the box environment variables and included support for multiple environments.

New Environment Variables Support

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

Exposing Environment Variables

Next.js allows you to expose variables using an environment variables file (.env), with included support for multiple environments. It works like this:

  • .env - Contains environment variables for all environments
  • .env.local - Local variable overrides for all environments
  • .env.[environment] - Environment variables for one environment. For example: .env.development
  • .env.[environment].local - Local variable overrides for one environment. For example: .env.development.local

Solution 5

npm i dotenv

Then add below code to next.config.js, restart the application and you are good to go!

// next.config.js

require('dotenv').config()
const webpack = require('webpack')

module.exports = {
  webpack: (config) => {
    config.plugins.push(
      new webpack.EnvironmentPlugin(process.env)
    )
    return config
  }
}

If your .env file is not located in same folder as next.config.js add path to your config like below,

require('dotenv').config({ path: 'path/to/.env' })
Share:
41,919
Cristian Flórez
Author by

Cristian Flórez

🤓Frontend Engineer with 7+ years experience working with different tech stacks. ReactJS, React-Native, Typescript, and Graphql lover.

Updated on November 16, 2021

Comments

  • Cristian Flórez
    Cristian Flórez over 2 years

    I would like to have different configuration files for the environment variables and be able to use them in my next project. I saw the example with dotenv.

    But I don't like to define the variables in the .env file and also define them in the config.next.js file. if for some reason I put the variables in the .env file but forget to put them in the config.next.js file the code starts having problems. Theres is a way to do it more eficiently?

    My scripts in package.json:

    "scripts": {
        "dev": "next",
        "build": "next build",
        "start": "next start",
        "lint": "eslint pages --ext .ts,.tsx,.js",
        "test": "jest",
        "commit": "git-cz",
        "dev:production": "dotenv next"
    },
    

    My .env vars

    TITULO=react, typescript, material ui App
    

    Component

    import { NextPage }          from 'next';
    import { FunctionComponent } from 'react';
    
    interface HelloWorldProps {
      nombre: string,
      saludo?: string
    }
    
    
    const HelloWorld: FunctionComponent<HelloWorldProps> = ({ nombre, saludo = 'noches' }: HelloWorldProps) => (
      <>
        <h1>Hola {nombre} buenas {saludo}</h1>
        {/* eslint-disable-next-line multiline-ternary */}
        <h2>{process.env.TITULO ? 'hola' : 'adios'}</h2>
      </>
    );
    
    const Home: NextPage = () => <HelloWorld nombre="cristian" />;
    
    export default Home;