Passing environment-dependent variables in webpack
There are two basic ways to achieve this.
DefinePlugin
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),
Note that this will just replace the matches "as is". That's why the string is in the format it is. You could have a more complex structure, such as an object there but you get the idea.
EnvironmentPlugin
new webpack.EnvironmentPlugin(['NODE_ENV'])
EnvironmentPlugin
uses DefinePlugin
internally and maps the environment values to code through it. Terser syntax.
Alias
Alternatively you could consume configuration through an aliased module. From consumer side it would look like this:
var config = require('config');
Configuration itself could look like this:
resolve: {
alias: {
config: path.join(__dirname, 'config', process.env.NODE_ENV)
}
}
Let's say process.env.NODE_ENV
is development
. It would map into ./config/development.js
then. The module it maps to can export configuration like this:
module.exports = {
testing: 'something',
...
};
Just another option, if you want to use only a cli interface, just use the define
option of webpack. I add the following script in my package.json
:
"build-production": "webpack -p --define process.env.NODE_ENV='\"production\"' --progress --colors"
So I just have to run npm run build-production
.
I investigated a couple of options on how to set environment-specific variables and ended up with this:
I have 2 webpack configs currently:
webpack.production.config.js
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('production'),
'API_URL': JSON.stringify('http://localhost:8080/bands')
}
}),
webpack.config.js
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('development'),
'API_URL': JSON.stringify('http://10.10.10.10:8080/bands')
}
}),
In my code I get the value of API_URL in this (brief) way:
const apiUrl = process.env.API_URL;
EDIT 3rd of Nov, 2016
Webpack docs has an example: https://webpack.js.org/plugins/define-plugin/#usage
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify("5fa3b9"),
BROWSER_SUPPORTS_HTML5: true,
TWO: "1+1",
"typeof window": JSON.stringify("object")
})
With ESLint you need to specifically allow undefined variables in code, if you have no-undef
rule on. http://eslint.org/docs/rules/no-undef like this:
/*global TWO*/
console.log('Running App version ' + TWO);
EDIT 7th of Sep, 2017 (Create-React-App specific)
If you're not into configuring too much, check out Create-React-App: Create-React-App - Adding Custom Environment Variables. Under the hood CRA uses Webpack anyway.
You can pass any command-line argument without additional plugins using --env
since webpack 2:
webpack --config webpack.config.js --env.foo=bar
Using the variable in webpack.config.js:
module.exports = function(env) {
if (env.foo === 'bar') {
// do something
}
}
Source
You can directly use the EnvironmentPlugin
available in webpack
to have access to any environment variable during the transpilation.
You just have to declare the plugin in your webpack.config.js
file:
var webpack = require('webpack');
module.exports = {
/* ... */
plugins = [
new webpack.EnvironmentPlugin(['NODE_ENV'])
]
};
Note that you must declare explicitly the name of the environment variables you want to use.