webpack-cli: NODE_ENV not set on process.env
Do you want to request a feature or report a bug?
Bug
What is the current behavior?
Currently, mode only sets the value for NODE_ENV in the DefinePlugin but not changes the process.env.NODE_ENV.
For example, Babel depends on this env variable and when used with webpack --mode=production it will still run in development mode.
If the current behavior is a bug, please provide the steps to reproduce.
Running webpack --silent --mode=production && echo $NODE_ENV
This will NOT print anything.
Run NODE_ENV=production && webpack --silent --mode=production && echo $NODE_ENV
This will print production
What is the expected behavior?
Running webpack --silent --mode=production && echo $NODE_ENV should print production
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 29
- Comments: 35 (8 by maintainers)
Commits related to this issue
- risteys: use purgecss in production Makes the CSS file smaller as it removes all the non-used classes from Tailwind. Only enabled in production builds as it is optimization and extend the build proce... — committed to dsgelab/risteys by vincent-octo 5 years ago
- Explicitly set the node environment variable - Webpack does not set this, but the processes it calls (like tailwind) need it to be set. - See https://github.com/webpack/webpack/issues/7074 for a lo... — committed to andrewkfiedler/ace by andrewkfiedler 4 years ago
- Explicitly set the node environment variable (#100) - Webpack does not set this, but the processes it calls (like tailwind) need it to be set. - See https://github.com/webpack/webpack/issues/7074 f... — committed to connexta/ace by andrewkfiedler 4 years ago
- Use webpack node-env flag see https://github.com/webpack/webpack-cli/issues/2362#issuecomment-771776945 — committed to D3SOX/d3sox.github.io by D3SOX 3 years ago
I think this bit of information should be reflected in the documentation: https://webpack.js.org/concepts/mode/. As it reads now - “Provides process.env.NODE_ENV with value XXXXXX”, this lead me to believe that passing the mode as a CLI argument set process.env.NODE_ENV for the whole environment.
But honestly I think that there is a problem with the mental model here. If something called in relation to node
process.envthen themodeshould set it to that value during compile time.The manual literally says:
And the docs for
sass-loaderincludes an example using:I guess this will silently use
style-loadersinceprocess.env.NODE_ENVis alwaysundefined?I was hoping to do something similar, so what’s the alternative?
How can I check which
--modeis being run, so I can make variations in mywebpack.config.jsbetweendevelopmentandproductionmodes?For future seekers, now we support
--node-env, what is benefits:cross-envpackage:Before:
Now (you can remove the
cross-envif you don’t use it somewhere else):modeoption respect the--node-envoption if you don’t set themodeoption explicit using CLI options or in configuration(s), i.e.--node-env productionsetprocess.env.NODE_ENVandmodetoproductionI get the same result But I found that
console.log(process.env); // {}console.log(process.env.NODE_ENV); // developmentI was very surprised that
--mode=productiondoesn’t setprocess.env.NODE_ENVwith valueproductionwithinwebpack.config.jsbut only provides this variable for your bundles.So basically just a replacement for the old fashioned:
To others looking for a solution, I found it here: export a function instead of an object, and it will be called with parsed/normalized environment and argument objects.
(I’m submitting a PR for the
sass-loaderexample, which doesn’t work.)Honestly, thanks a million @mindplay-dk, this was driving me nuts… I never realised there was an argv being passed in. Just to have it here:
This is an absolutely perfect example of why my love meter for “modern javascript” constantly veers back into the negative
I’d argue it should actually set the variable to allow related tools be executed in the right context.
babel-loaderdoesn’t rely on it per-se but since the loader executesbabel-corewhich relies on it, it might break things right now.Then the documentation is misleading and needs to be updated? It should probably explicitly say that it only does
new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),&& echo $NODE_ENVwill showNODE_ENVvalue after previous command finished successfully, webpack will change it only while it runs, it doesn’t change it for the entire system.I don’t know exactly at what point exactly webpack sets
process.env.NODE_ENV, also don’t know if loaders should rely on it, by reading https://github.com/webpack/webpack/issues/2537#issuecomment-221024348 one could conclude that it doesn’t affect loaders source environment.So you still have to set it at command level, so I would affect entire execution context.
IMHO if “mode” is specified, no matter wether via command line or the configuration file, process.env.NODE_ENV should be set to that value, the behaviour should be as simple as that. I’ve spent days trying to understand why it wasn’t being set, and the behaviour of the “-p” flag is totally misleading 😕
@adamwathan I suggested it in my comment (which I incidentally wrote after I got the purge option to work with Tailwind!)
Nothing wrong with that. But using https://github.com/kentcdodds/cross-env instead seems to be a very popular (and safer) alternative, and is used by all kinds of projects.
Alternatively, I do it like this:
https://stackoverflow.com/questions/55259238/what-is-the-difference-between-webpack-env-production-and-mode-production
Basically --mode just sets “process.env.NODE_ENV” on DefinePlugin only. And you can access it inside function exported from your webpack.config.js.
–env also has nothing to do with process.env and it operates on object passed to your exported function.
One trick would be to assign process.env.NODE_ENV manually like this:
process.env.NODE_ENV will be correctly defined in other configs you use like postcss.config.js
or just use cross-env and if you want --mode functionality as well do this(for webpack to add it to DefinePlugin as well):
Note it won’t be available in
argv.modethen if you don’t pass it with cmd linemy idea.
running
webpackorNODE_ENV=development webpacknot set --mode option.
Best regards,
In package.json “scripts”: { “dev”: “webpack --mode development --watch”, “build”: “webpack --mode production”, }
In webpack.config.js module.exports = (env, options) => { const devMode = options.mode !== ‘production’; return { entry: … output: … module: { … { test: /.(sa|sc|c)ss$/, use: [ devMode ? “style-loader” : MiniCssExtractPlugin.loader, “css-loader”, “sass-loader” ] }, … } … } }
Thanks,it works
I haven’t seen anyone suggesting setting the variable for the script execution on the command line just like this:
Am I missing a reason this isn’t a good solution?
first try
second try
“scripts”: { “test”: “echo "Error: no test specified" && exit 1”, “dev”: “webpack --config ./conf/webpack.config.js --mode development”, “build”: "webpack --config ./conf/webpack.config.js --mode production " },
2 . webpack.config.js
add plugin parameter value into webpack config. module.exports = { entry: …, plugins: [ new webpack.DefinePlugin({ ‘process.env’: { ‘NODE_ENV’: ‘"’ + process.env.NODE_ENV + ‘"’ } }), ], output: {…} }
NODE_ENV=dev npm run dev or NODE_ENV=prod npm run build
It will set the environment as you pass on command line.