简体   繁体   中英

How to load environment variables in React

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?

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)
    ]
  };

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!

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!

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!

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM