11

I've been trying to load environment variables in React and I can't seem to figure it out. I have tried multiple aproaches:

Load them using the dotenv-webpack package

webpack.config.dev.js

const merge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const template = require('html-webpack-template');
const Dotenv = require('dotenv-webpack');
const baseConfig = require('./webpack.config.base');

module.exports = merge(baseConfig, {
  mode: 'production',
  plugins: [
    new HtmlWebpackPlugin({
      template,
      inject: false,
      appMountId: 'app',
      mobile: true,
      lang: 'es-ES',
      title: 'My App',
      meta: [
        {
          name: 'description',
          content: 'My App',
        },
      ],
    }),
    new Dotenv(),
  ],
});

.env

API_HOST=http://localhost:8000
REACT_APP_API_HOST=http://localhost:8000

Passing it directly on the package.json script:

"start": "webpack-dev-server --config ./webpack.config.dev.js"

Using .env on the webpack command

webpack --env.API_HOST=http://localhost:8000

Using webpack.environmentPlugin

const webpack = require('webpack');
const merge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const template = require('html-webpack-template');
const baseConfig = require('./webpack.config.base');

module.exports = merge(baseConfig, {
  mode: 'development',
  devtool: 'cheap-module-source-map',
  devServer: {
    publicPath: '/',
    contentBase: './dist',
    compress: true,
    stats: 'minimal',
    overlay: true,
    historyApiFallback: true,
    port: 8081,
    hot: true,
  },
  plugins: [
    new HtmlWebpackPlugin({
      template,
      devServer: 'http://localhost:8081',
      inject: false,
      appMountId: 'app',
      mobile: true,
      lang: 'es-ES',
      title: 'My App',
      meta: [
        {
          name: 'description',
          content: 'React template.',
        },
      ],
    }),
    new webpack.EnvironmentPlugin({
      API_HOST: 'http://localhost:8000',
    }),
  ],
});

None of this approaches work and when I try to access process.env variables in my React code I get undefined Any ideas of what I could be doing wrong?

5 Answers 5

4

I've been fighting with environment variables myself for some time, when I wanted to provide settings to the Firebase project but not load them into the public repository.

As far as I know, you need to name you environment variables should always start with the prefix REACT_APP_. You can define them whereever you like, but if you created your app with create-react-app tool then you can put your variables in .env file, or a few other files - (https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables)

The pain for me started when I wanted to make my own files, because I had two different Firebase projects - one for staging and one for production.

I end up with using react-app-env module which helped with: - defining my own files - staging.env and production.env - auto prefix my variables with REACT_APP_

For example:

I have defined Firebase ApiKey in staging.env file: API_KEY=xxxxxxxxxxxxxxxxxxx

when I use it in my firebase.js file, I use it as:

const config = {
    apiKey: process.env.REACT_APP_API_KEY,
}

And to make sure that I develop against staging environment (Firebase project) I've changed my package.json to:

"scripts": {
    "start": "react-app-env --env-file=staging.env start",
  },

Hope that helps!

Sign up to request clarification or add additional context in comments.

2 Comments

For future reference, react-app-env has been deprecated, but the same outcome can be achieved using the env-cmd package as outlined in this stackoverflow response.
whoever made this decision, to force the prefix REACT_APP_ needs to seriously question their technical ability. I would have simply added a mechanism to only read defined vars, instead of adding a prefix
3

You need to specify the webpack config file correct. You will need to create a separate config for dev. (webpack.config.dev.js)

Example here.

scripts: {
    "dev": "webpack --env.API_HOST=http://localhost:8000 --config webpack.config.dev.js"
}

Also, you need to use Webpack.DefinePlugin.

plugins: [
  ...
  new webpack.DefinePlugin({ `process.env.API_HOST`: JSON.stringify(${env.API_HOST}) })
]

or you can use reduce to make it more comprehensive.

  const envKeys = Object.keys(env).reduce((prev, next) => {
    prev[`process.env.${next}`] = JSON.stringify(env[next]);
    return prev;
  }, {});

  return {
    plugins: [
      ...
      new webpack.DefinePlugin(envKeys)
    ]
  };

3 Comments

Yeah. I have a webpack file for each environment
I updated my answer. You need to use Webpack.DefinePlugin.
Yeah I forgot to mention that I have tried that already too. EnvironmentPlugin and DefinePlugin. None seems to be working :(
0

Agree with @Philip's answer, this is how I structure my dev.config.js

  ...
  plugins: [
    new webpack.DefinePlugin({
      // process.env
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV),
        WHY_DID_YOU_UPDATE: process.env.WHY_DID_YOU_UPDATE,
      },
      // my other global flags
      __CLIENT__: true,
      __SERVER__: false,
      __DEVELOPMENT__: true,
      __DEVTOOLS__: true
    }),
  ]

I also use better-npm-run to manage my package.json, where you can easily manage the env variables

  "betterScripts": {
    "dev": {
      "command": "concurrently --kill-others \"better-npm-run watch-client\" \"better-npm-run start-dev\" \"gulp watch --gulpfile semantic/gulpfile.js\""
    },
    "why-did-you-update": {
      "command": "better-npm-run dev",
      "env": {
        "WHY_DID_YOU_UPDATE": true
      }
    },
    "watch-client": {
      "command": "node webpack/webpack-dev-server.js",
      "env": {
        "UV_THREADPOOL_SIZE": 100,
        "NODE_ENV": "development",
        "NODE_PATH": "./src",
        "PORT": 3000
      }
    },
    "build": {
      "command": "webpack --verbose --colors --display-error-details --config webpack/prod.config.js"
    }
  },

Hope this information helps you too!

Comments

0

I find a simple solution for this. You need to install 'dotenv-webpack', then add this configuration to your webpack config:

const Dotenv = require('dotenv-webpack');

...
  plugins: [
    new Dotenv(),
  ],
...

.env

DB_HOST=127.0.0.1
DB_PASS=foobar
S3_API=mysecretkey

Finally you can access your env variables in your app

console.log(process.env.DB_PASS);

From the docs: the .env values for DB_HOST and S3_API are NOT present in our bundle, as they were never referenced (as process.env.[VAR_NAME]) in the code. Hope it helps!

Comments

0

You can specify environment variables in the package.json scripts section:

{
  ...
  "scripts": {
    "start": NODE_ENV=development webpack-dev-server
  },
  ...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.