Reputation: 323
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?
Upvotes: 11
Views: 9493
Reputation: 1989
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!
Upvotes: 4
Reputation: 870
You can specify environment variables in the package.json
scripts section:
{
...
"scripts": {
"start": NODE_ENV=development webpack-dev-server
},
...
}
Upvotes: 0
Reputation: 1014
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!
Upvotes: 0
Reputation: 6556
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!
Upvotes: 0
Reputation: 481
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)
]
};
Upvotes: 3