webpack: DefinePlugin does not inject variable
I have been trying to figure this out for over an hour now. Here is the subject code:
const ENVIRONMENT = process.env.NODE_ENV;
const BASENAME = process.env.APP_BASENAME;
console.log('process.env', {
ENVIRONMENT: ENVIRONMENT,
'process.env': process.env,
NODE_ENV: process.env.NODE_ENV,
APP_BASENAME: process.env.APP_BASENAME
});
if (ENVIRONMENT !== 'development' && ENVIRONMENT !== 'production') {
throw new Error('Unknown ENVIRONMENT.');
}
export {
BASENAME,
ENVIRONMENT
};
Here is my webpack config:
const webpack = require('webpack');
const path = require('path');
module.exports = {
devtool: 'source-map',
debug: false,
context: __dirname,
entry: {
'app': [
path.resolve(__dirname, './src/app')
]
},
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].js',
publicPath: '/static/'
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compressor: {
/* eslint-disable camelcase */
screw_ie8: true,
/* eslint-enable */
warnings: false
}
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"',
'process.env.APP_BASENAME': '"' + (process.env.APP_BASENAME || '') + '"'
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
APP_BASENAME: '"' + (process.env.APP_BASENAME || '') + '"'
}
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.NoErrorsPlugin()
],
module: {
loaders: [
{
include: path.resolve(__dirname, './src'),
loader: 'babel',
test: /\.js$/,
},
{
loaders: [
'style?sourceMap',
'css?modules&importLoaders=1&localIdentName=[name]___[local]___[hash:base64:5]',
'resolve-url',
'sass?sourceMap'
],
test: /\.scss$/
}
]
}
};
As you can see, I have tried multiple methods of using DefinePlugin
:
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"',
'process.env.APP_BASENAME': '"' + (process.env.APP_BASENAME || '') + '"'
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
APP_BASENAME: '"' + (process.env.APP_BASENAME || '') + '"'
}
}),
Here is the console output:
{
APP_BASENAME: "/campaign-master/upload-static",
ENVIRONMENT: undefined,
NODE_ENV: undefined,
process.env: {
APP_BASENAME: "/campaign-master/upload-static",
NODE_ENV: "production"
}
}
The script execution ends with an exception:
Uncaught Error: Unknown ENVIRONMENT.
As a result of the condition that you can see in the config.js
.
What is the reason process.env.NODE_ENV
is not getting replaced?
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 21
- Comments: 34 (4 by maintainers)
Hmm, I was just having this issue and it was trolling me.
process.env
was showing as an empty object, but after I read this https://github.com/webpack/webpack/issues/868 I tried explicitly callingprocess.env.NODE_ENV
andprocess.env.APP_VERSION
, and boom it worked fine. Watchout for that. It could be some of yours’ problems…Inside some module:
console.log(process.env.APP_VERSION) === 0.0.1
console.log(process.env) === {}
@amackintosh This is because
DefinePlugin
doesn’t build any object - it just replaces all occurrences ofprocess.env.NODE_ENV
in code with the constant you provided. In short, this works like find-and-replace variable with value 😃I am having the same problem with webpack-3.5.5. typescript 2.5.2
That was painful experience.
My
.babelrc
has been configured as:while I was executing webpack using:
i.e.
babel-preset-react-hmre
is breakingDefinePlugin
.As many people have pointed out, the substitution is a compile-time operation (static), i.e. it is carried out when the bundle is built, as opposed to being evaluated when the resulting application is run (dynamic) in node or the browser. You may pass in a computed value inside webpack.config.js but the value that ends up inside the bundle will be a fixed value determined before the application is ever run. An easy way to distinguish these is to ask yourself: Do I need to know the actual value of the variable before the bundle is built? if yes, then DefinePlugin can help you with that. If not, then you need another solution where the process that serves your bundle to the client will pass in the required values)
In other words: the purpose is to modify the bundle being built (e.g. a development bundle that facilitates debugging vs. highly optimized production bundle). It is NOT a means to modify the behaviour of an already built bundle when it is run!
Another significant thing I noticed is that it doesn’t work well in combination with webpack’s --watch mode. That also makes sense as webpack will aggressively cache already compiled modules and only recompile them if the watched corresponding source files are changed. If we change the environment variables we pass in, the source files still remain unchanged thus webpack will happily skip recompiling those modules if it’s operating in watch mode. We can work around this by deleting the cache before running webpack:
@donce Thanks a lot. It works!! I have been researching the reason why everything was undefined when I tried getting the value from the
window
object. ThisDefinePlugin
thing is really a trick.I should confess that the problem I reported was actually of my own making. Sadly, I can’t actually recall the details of my error, but I can confirm that DefinePlugin is working ok for me now (using Webpack 3.5.5). eg. the following works as expected:
new webpack.DefinePlugin({ ‘process.env.NODE_ENV’: JSON.stringify(process.env.NODE_ENV), ‘process.env.BUILD_TARGET’: JSON.stringify(build), }),
hth.
Good Solution
Working Done.
plugins: [ new webpack.DefinePlugin({ process: { env: { VERSION: JSON.stringify("5fa3b99999"), ETC: "..." } } }) ]
I’m not sure why it’s called “DefinePlugin” — it’s more like a “identifier substitution plugin”.
Also you might want to set
node: false
in the webpack config. By default webpack will mock node globals for the browser, which is whyprocess
andprocess.env
are defined instead of being completely undefined. That threw me off for a second.Hey @gajus, I think I’m facing the same problem that you did - DefinePlugin just isn’t injecting the variables. I’m very new to webpack, please excuse my knowledge gaps. What exactly was the problem with babel-preset-react-hmre, and how is it fixed by updating .babelrc?