Skip to content

Instantly share code, notes, and snippets.

@markerikson
Last active January 18, 2018 03:01
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markerikson/ead940a93a2a877dc97824e5f839840f to your computer and use it in GitHub Desktop.
Save markerikson/ead940a93a2a877dc97824e5f839840f to your computer and use it in GitHub Desktop.
Webpack and confusion with process.env.NODE_ENV

2016-07-10 - #webpack - Initial discussion and confusion

[09:38 PM] Steven: No matter what I do, I cannot get the NODE_ENV to be production for the purposes of webpack compiling
I have tried every example on the web

    plugins: [  
        new webpack.DefinePlugin({  
            'process.env':{  
                'NODE_ENV': JSON.stringify('production')  
            }  
        }),  

[09:41 PM] Steven: in the actual running code it's ther

console.log(`NODE_ENV ${process.env.NODE_ENV}`);  

// NODE_ENV production
but throughout my config i'm checking that variable and it's not doing the things that it should if it was true
for example

           {  
                test: /\.(css|scss)$/,  
                loader: process.env.NODE_ENV === 'production' ? ExtractTextPlugin.extract(cssLoader) : 'style!' + cssLoader,  
                exclude: /node_modules/  
            }  

these are behaving as if that was fale
[09:44 PM] acemarke: uh... the config and your app code are not the same thing... :)
[09:46 PM] Steven: https://github.com/topheman/react-es6-redux/blob/master/webpack.config.js
const NODE_ENV = process.env.NODE_ENV ? process.env.NODE_ENV.toLowerCase() : 'development';
[09:46 PM] acemarke: lot of config stuff in there
[09:46 PM] Steven: according to everything i've read (this is just ONE example) that variable should be available during compile time
i can paste 10 other urls
if you want
the point is, THIS IS THE METHOD everyone is using
and yet it doesn't work for me
[09:47 PM] acemarke: I'm saying that DefinePlugin affects the code that Webpack is processing
[09:47 PM] Steven: is there a way i can confirm that? like checking to see if react is in production mode?
[09:48 PM] acemarke: pause for a minute and lemme make sure I understand the issue properly
[09:48 PM] Steven: I'll start again and be clear 😃
[09:48 PM] acemarke: your concern is that lines like devtool: process.env.NODE_ENV === 'production' ? 'source-map' : 'eval', are not producing the result you expect?
[09:48 PM] Steven: I have a series of things in the webpack.config.js file that are dependent on whether it's production or dev
that is just one
here take a look
[09:48 PM] acemarke: and you are expecting that use of the DefinePlugin is going to affect that line?
[09:49 PM] Steven: https://gist.github.com/stevensacks/0d6341002f7c530136ceb464feae0be2
i'm expecting that I can use a variable to determine whether the config should run in dev or prod mode
i have tried stuff like adding params to the npm command - no dice
[09:49 PM] acemarke: right, but that has to be determined before this config generation script starts executing
[09:50 PM] Steven: the only working example of that that I have found is webpack 2 and there's almost no documentation on webpack 2
[09:50 PM] acemarke: this has nothing to do with Webpack 2
this is strictly a Node thing
[09:50 PM] Steven: ok
[09:51 PM] acemarke: off the top of my head, Node determines the initial value of the process.env.NODE_ENV variable based on the current value of the NODE_ENV environment variable when the Node process was launched
[09:51 PM] Steven: fair enough
[09:52 PM] Kovensky: isn't process.env a "live variable"?
[09:52 PM] acemarke: not sure what it default to
[09:52 PM] Kovensky: it defaults to undefined, unless you export NODE_ENV from the parent process (such as a shell)
[09:52 PM] acemarke: but the key point is that in order for the Webpack config generation script to have the correct NODE_ENV, value, that has to be set up beforehand
[09:52 PM] Steven: 1. how do I set it? (pass it in via CLI?)
2. how do i read it?
[09:52 PM] acemarke: you read it the same way you're reading it
you define it however environment variables are defined on your platform
on Windows, you'd do:

set NODE_ENV="production"  
node runMyBuildLogic.js  

(still hazy on exactly how the quotes work right in this process, but you get the idea)
under Linux/OSX, whatever the right export syntax is for environment variables
[09:54 PM] Kovensky: on bourne shells (sh, bash, zsh, etc) you can either do: NODE_ENV="value" node ... (set NODE_ENV only for that command) or export NODE_ENV="value" (every command run after the export will receive NODE_ENV with that value)
[09:54 PM] acemarke: you can also use various Node-based utilities to pre-set environment variables and bootstrap your real script
[09:54 PM] Steven: i'm on osx
[09:54 PM] Kovensky: that's a bourne shell
[09:55 PM] Steven: one thing i've failed to figure out is how i can write my webpack.config.js in ES6 and babel it to ES5 so it will build under Node 4.x
so i'm stuck writing it in ES5 for the time being
webpack documentation/tutorials are sorely lacking in this regard
[09:56 PM] acemarke: under Node 6, you can use just about all of ES6 except modules
[09:56 PM] Steven: it's the wild west
yes but I'm using AWS Lambda on the backend and they only support node 4.x
[09:56 PM] Kovensky: on node 4, you can use let/const and template strings
but you have to put 'use strict' as the first line of the file
[09:56 PM] acemarke: as for Webpack for server code... what's the issue?
write code, run Webpack, spit out bundle
(granted not something I've necessarily tried myself)
[09:57 PM] Kovensky: also, the version on AWS Lambda only matters if you're running webpack itself in it
[09:57 PM] Steven: the backend is running node 4 - it can't read ES6 natively - so i need to babel-transpile my webpack.config.js just before it executes (essentially)
[09:57 PM] acemarke: "just before"?
[09:57 PM] Steven: as it runs
[09:58 PM] acemarke: why?
[09:58 PM] Kovensky: http://node.green/ <-- features you can use (but it appears to lie; shorthand properties don't work without --harmony)
[09:58 PM] Steven: i've read that it can be done
[09:58 PM] acemarke: Webpack is generally a one-time precompile thing
[09:58 PM] Kovensky: the backend doesn't care what version your build script runs on -- the backend will run the output of webpack, not webpack itself
[09:59 PM] Steven: see, this is the stuff that is undocumented
[09:59 PM] acemarke: ???
[09:59 PM] Steven: webpack is TERRIBLY documented
[09:59 PM] acemarke: certainly the primary use case is client code
but I'm not sure what you're complaining about specifically
[09:59 PM] Steven: i'm trying to test the production build locally
[09:59 PM] acemarke: what actual things are you complaining about?
[09:59 PM] Steven: and i cannot figure out how to get it to think it's in production mode
and every example i see online doesn't worrk
[10:00 PM] acemarke: because you don't have your environment variable defined correctly before you build
[10:00 PM] Steven: for the reason you just stated
[10:00 PM] acemarke: which is a Node thing, not a Webpack thing
[10:00 PM] Steven: right
and do you see the issue here?
[10:00 PM] acemarke: just googling for process.env.NODE_ENV turns up dozens of articles
[10:00 PM] Steven: yes
almost all of them say use definePlugin
which is "too late"
[10:00 PM] acemarke: yes. that's what affects the output of Webpack
[10:00 PM] Steven: right
[10:00 PM] acemarke: the point is that your build script is in fact a Node script
[10:00 PM] Steven: see i didn't get that
until now
[10:01 PM] acemarke: and that has absolutely nothing to do with Webpack itself
[10:01 PM] Steven: now that is a dodge
if i ever heard one
[10:01 PM] acemarke: nope
[10:01 PM] Steven: that's passing the buck
webpack runs in this envrionment
[10:01 PM] acemarke: I mean, just searching for NODE_ENV turns up all kinds of articles about Express in production and so on
[10:01 PM] Steven: and this is a very common thing that people want to do in webpack
[10:01 PM] acemarke: process.env.NODE_ENV is a NODE concept
[10:01 PM] Steven: so it's the responsibility of webpack authors to provide this information
and not say "well, if you don't know how to use node.js, too bad."
tell me how to do this thing that everyone probably needs to do to use webpack correctly
[10:02 PM] acemarke: do you understand the concept of "system environment variables"?
[10:02 PM] Steven: roughly but i'm a front-end dev, not a dev ops person
[10:03 PM] acemarke: okay. so, that's what you need to go learn
[10:03 PM] Steven: so my experience with this stuff is like MOST front-end devs - very limited and brand new to it
This is the problem
THIS IS THE PROBLEM
[10:03 PM] acemarke: don't blame Webpack for not documenting a systems-level concep[t
[10:03 PM] Kovensky: the define plugin is when you want to pass the process.env.NODE_ENV to files that are bundled; this is used, for example, in React, to disable debugging code if it's equal to "production"
[10:03 PM] acemarke: I agree their docs are scattershot
but it's not Webpack's responsibility to document Windows or OSX or Linux system concepts
or Webpack's job to document Node's API
[10:04 PM] Steven: "go learn this thing you didn't know you need to learn because this tool we wrote (webpack) for helping you build your projects requires it and we're not going to tell you the few things you need to know to use our tool, unlike our competitors (browserify, gulp, etc.) who tell front-end devs the things they need to know in clear documentation because they acknowledge that most front-end developers haven't used node.js enough to know this stuff well enough to even know what they're supposed to look for"
get what i'm saying?
It's not their job
But if they want their build script to be widely adopted they need to make it easier for people who aren't node.js experts
[10:05 PM] acemarke: so submit a PR?
[10:05 PM] Steven: Browserify, Gulp, Grunt, they all tell you exactly what to do even if it's "outside their responsibility"
i have developer friends who are amazing front-end devs but have limited node.js experience and find the process of using and learning webpack to be really difficult
and yet they know they need to use it
[10:07 PM] acemarke: for that matter, the first three search results for node process node_env are SO pages answering what it is and how to set it
[10:07 PM] Steven: see that one word
prcoess
[10:07 PM] acemarke: including http://stackoverflow.com/questions/9198310/how-to-set-node-env-to-production-development-in-os-x
[10:07 PM] Steven: YOU knew to type that
when i googled
process.env.NODE_ENV
i got the definePlugin stuff
see the confusion?
[10:07 PM] acemarke: uh... the config file you pasted includes collapseWhitespace: process.env.NODE_ENV === 'production'
[10:08 PM] Steven: if you don't know what you're supposed to search for, you won't get what you're looking for
[10:08 PM] acemarke: I mean, it's right there
[10:08 PM] Steven: this is the problem inherent in webpack's documentation
that's what YOU say
it isn't
the way you typed it shows different result
[10:08 PM] acemarke: stop. where did all this config stuff come from?
did you write it yourself, or copy-paste?
[10:10 PM] Steven: everything is pieced together from various people's webpack.config.js files that you can find on the web. why? because the webpack documentation is poor, there are almost no good tutorials, and what's truly indicative of how terrible it is, everyone's webpack.config.js file is totally different.
i mean, clearly it's a problem
you denying it's a problem doesn't mean it's not one
everyone has trouble with webpack
[10:10 PM] acemarke: well, the "they're all differnt" aspect is simply because the output is plain JSON, and arbitrary code can be used to assemble it
out of curiosity, did you try reading any of the articles linked in my list?
[10:11 PM] Steven: i've seen at least 5 different ways to write a webpack.config.js
which list?
[10:11 PM] acemarke: https://github.com/markerikson/react-redux-links/blob/master/webpack-tutorials.md and https://github.com/markerikson/react-redux-links/blob/master/webpack-advanced-techniques.md
[10:11 PM] Steven: i'll ake a look
you know what
here's a suggestion 😃
[10:12 PM] acemarke: anyway, I think I'm about done with this conversation for now. You seem like a smart guy, but you spend a lot of time ranting about stuff that seems pretty silly, and I'm getting a bit tired of responding to that
[10:12 PM] Steven: put those two links into the description of this channel
like you did for #redux
if those were there at the top of #webpack here, I would have checked them first before asking 😃
i'm not ranting. i'm trying to explain why i hit walls and it feels to me like you're telling me it's my fault because the information is out there even though I'm telling you I spent a lot of time looking and came up empty
it's like your invalidating my experience
and i'm trying to explain that it's not just me
[10:13 PM] acemarke: maybe Google's giving me different results than it does for you, but it sure gave me relevant bits of info just by searching for those terms, either singly or inside of quotes
yes, I did already know what I was looking for in this case
maybe I'm just used to following trails through articles to assemble info
I think what's really bothering me is the way you seem to jump to blaming people. JS engine devs are all apparently stupid for following the spec when it comes to built-in functions, and it's the Webpack devs' fault for not documenting the APIs of the underlying runtime
and I'll shut up at this point
[10:16 PM] Steven: ot
i.e. haven't built anything in node
And that, like most people in that position, go looking for examples of how to do the limited thing they need to do to get up and running
Browserify, Gulp and Grunt all approach their documentation from that perspective
"you probably don't know about all this. don't worry, you don't need to know everything to get started. here's what you need to know to get what you need"
that's the approach
it's inclusive and empathetic
at any rate, these two links you posted are everything i (and other people i know) have been looking for. it would be great if these were linked to on the official webpack site and at the top of this board @acemarke

2016-07-12 - #webpack - Clarification and summary of concepts

[02:06 PM] acemarke: @Steven : a couple other thoughts on the whole NODE_ENV thing. First, per my comments, it really is a Node concept. It's a system environment variable that Node exposes to your application, and apparently the Express web server library popularized using its value to determine whether to do optimizations or not
[02:08 PM] acemarke: Second, because of its use within the Node ecosystem, web-focused libraries also started using it to determine whether to they were being run in a "development" environment vs a "production" environment, with corresponding optimizations. For example, React uses that as the equivalent of a C #ifdef to act as conditional checking for debug logging and perf tracking. If process.env.NODE_ENV is set to "production", all those if clauses will evaluate to false.
Third, in conjunction with a tool like UglifyJS that does minification and removal of dead code blocks, a clause that is surrounded with if(process.env.NODE_ENV !== "development") will be dead code and stripped out, reducing bundled code size and execution time
However: because the NODE_ENV environment variable and the corresponding process.env.NODE_ENV runtime field are strictly Node-specific concepts, by default that value does not exist in client-side code
which is where things like the Webpack DefinePlugin come in. Since Webpack is doing transformation of your code anyway, it can force the existence of global values such as process.env.NODE_ENV.
[02:14 PM] acemarke: But, here's the key: it could set that value to anything, based on any condition you want, as you are generating your Webpack config. For example, I could have a webpack.production.config.js Webpack config file that always uses DefinePlugin to set that to "production". It wouldn't have to be checking the actual current value of the "real" process.env.NODE_ENV variable while generating the Webpack config, because I would know that any time I'm doing a "production" build, I would want to set that value in the client code to "production'.
But, this is where the "code I'm running as part of my build process" and "code I'm outputting from my build process" worlds come together
[02:17 PM] acemarke: Because your build script is itself most likely to be Javascript code running under Node, it's going to have process.env.NODE_ENV available to it as it runs. Because so many tools and libraries already share the convention of using that field's value to determine their dev-vs-production status, the common convention is to use the current value of that field inside the build script as it's running to also determine the value of that field as applied to the client code being transformed
hopefully that clears things up slightly
I do want to address a few of your thoughts
first, while obviously everyone has had different paths in their programming careers and learning experiences, I would guess that "many" React devs are coming to it from a Node background, and would already have at least a passing familiarity with some of its concepts
and at least partly because of that, most Webpack tutorials jump straight into "here's how you set up your Webpack config", and don't talk about the Node-oriented aspects
I will say that the relationship between the server-side "value of NODE_ENV in your build script" and the client-side "value of NODE_ENV as applied to your code" is not immediately made clear by most articles I've glanced at
on the flip side, simply searching for node_env turns up discussions like http://stackoverflow.com/questions/16978256/what-is-node-env-in-express and http://apmblog.dynatrace.com/2015/07/22/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/
which at least give a fairly decent description of what it is
[02:25 PM] acemarke: Ultimately, this all comes down to a few key points:

  1. NODE_ENV is a system environment variable that Node exposes into running scripts
  2. It's used by convention to determine dev-vs-prod behavior, by both server tools, build scripts, and client-side libraries
  3. It's commonly used inside of Webpack config generation as both an input value and an output value, but the tie between the two is still just convention
  4. It's not a Webpack-specific concept, and it's not up to the Webpack team to document it
    all that said, I will agree that I'm not seeing articles that specifically tie all that information together

2016-07-12 - #redux - ways to improve Webpack docs

[04:51 PM] acemarke: changing topic for a minute: did my explanation in #webpack help clarify things at all?
[04:52 PM] Steven: yeah and on a personal note, i apologize that i came across as ranty. my impact was not my intention.
[04:53 PM] acemarke: I'll definitely admit I was getting kinda frustrated on my ned
and I do understand those days when you've been digging for hours and stuff isn't working
[04:57 PM] Steven: that "fatigue" article (and Dan's tweet yesterday about it) is heavily on my mind. it's like, sure, once you know all this stuff it all make sense, but for developers like me who spent all my career on front-end (AS1/2/3 before JS) and none on back, and not having experience with node outside of "just run these commands to get your front-end up and running", when you hit a wall using a tool like webpack that depends on node.js, and it's expected that you have to go digging for something you don't even know what you're looking for, it definitely is fatiguing. my "rant" was intended to say that even though it's not specifically part of whatever library you're working on, but part of the larger ecosystem, if the author wants their library to be widely used, it would be better for the community if they said "hey, this isn't technically part of my lib, but it's a common use case for my lib, so just in case you don't know node.js at more than a superficial level, here's the command to achieve this common need."
your collection of webpack articles, tutorials, etc. is exactly what me and some of my colleagues in the industry have been looking for
[04:59 PM] acemarke: yay?
[04:59 PM] Steven: we've been largely on our own, looking at webpack.config.js files in various github projects.
trying to grok it that way
but everyone has their own way of doing it, and clearly some people know node.js better than others, and webpack better than others.
[04:59 PM] acemarke: yeah, a lot of my own project's config was based on looking at like 15 different boilerplates and picking out the bits I liked/needed, as well as googling / experimenting
[05:00 PM] Steven: so you pick up what you can in an effort to move forward on your project (the front-end part, not the compilation/bundling part), but eventually you hit walls.
[05:00 PM] acemarke: and yeah, I can definitely see your point regarding "common use cases"
have you seen the posts from the Webpack team regarding plans for improved docs and Webpack2 info?
this would probably be really good feedback for them
[05:01 PM] Steven: Yeah I didn't phrase it that way, though, and that's my bad. I was definitely coming off as "this sucks. why don't they make it easier" instead of "it would be nice if they could explain this because it's a point of frustration."
No excuse, but I think fatigue had set in.
[05:02 PM] acemarke: yeah, I was interpreting your comments as "this is clearly a thing that Webpack should have documented", and feeling confused because it's not a thing they're responsible for
[05:02 PM] Steven: In two months I've learned Webpack+React+Redux+Functional Programming+ES2015 all back to back.
[05:02 PM] acemarke: yeah, that is definitely a pretty hefty workload
it's a great time to be a JS dev, and it's an awful time to be a JS dev
[05:03 PM] Steven: Well I didn't know that it was going to be when I started lol
The rabbit hole just kept going and going
(and not in that order, btw)
[05:04 PM] acemarke: fyi, https://medium.com/webpack/webpack-2-docs-team-wants-you-20876c59e964
which points to https://github.com/webpack/webpack.io/issues?q=is%3Aopen+is%3Aissue+label%3Adocumentation
[05:05 PM] Steven: From my perspective, being able to build React using Webpack in production mode should be included in the docs since it's A) pretty easy when you know how, and B) a lot of devs are learning the minimum they need to get webpack up and running a react project and might not know node.js.
I'll check it out
thanks
And every example I found said to use the webpack.DefinePlugin (which was not actually correct)>.
And I searched a lot
And I think I had just gotten to a point where I was overwhelmed and wanted somebody to hold my hand for once haha.
[05:07 PM] acemarke: yeah, per my comment today, the key for optimizing numerous client-side libs is to use DefinePlugin to specify process.env.NODE_ENV as "production" when the client-side code is transformed, and then UglifyJS will zap the now-dead code branches
[05:08 PM] Steven: are you talking about tree shaking?
[05:08 PM] acemarke: but then there's the usual assumption that the client-side version of that value is coming from whatever it is inside of the build script
not quite
[05:08 PM] Steven: i know that's the new hotness in webpack 2
[05:09 PM] acemarke: so let's say that inside of a React file, you have:

function implementSomeReactBehavior() {  
    // do actual work part 1  
  
    if(process.env.NODE_ENV !== "production") {  
        // do debug-only work, like recording perf stats  
    }  
  
    // do actual work part 2  
}  

like, in React itself
[05:09 PM] Steven: yeah
[05:10 PM] acemarke: so the standard unminified file has that if branch in there, and will happily run it, including the (possibly expensive) debug logging, perf recording, whatever
when you use DefinePlugin to set process.env.NODE_ENV to "production", that if statement is now always false
in fact, I think it actually replaces the verbatim variable name entirely
so that the statement becomes if("production" !== "production")
so now you have a flat-out dead branch of code
and when UglifyJS analyzes the code, it says "oh hey, dead branch, I can wipe that out entirely"
[05:11 PM] Steven: yeah i understand the concept. i wrote a framework for Flash called Gaia years ago and I had optimization options to comment out chunks of code for features you weren't using to reduce the footprint of the framework core.
for some reason, i thought that babel's transpilation from ES2015 to ES5 did a JS minification already. i didn't know you had to explicitly add UglifyJS plugin into the chain for production.
[05:14 PM] acemarke: yeah. Babel transpiles code, Webpack transforms code, Uglify transforms code.... they just do different parts of it :)
technically, I think calling webpack -p from the commandline specifies use of UglifyPlugin, but most of the time a real-world config specifies it manually
[05:15 PM] Steven: thing is, there are some steps that i'm completely ignorant of (and many others are as well) when it comes to the "final steps" of deploying your webpack+react+redux project on production.
and this is not an uncommon problem in JS development
i mean, EDM.com, as an example, is running Angular in development mode.
i discovered it when i looked at the console for it
[05:16 PM] acemarke: seriously, this is great feedback to give to the Webpack team
[05:16 PM] Steven: will do
now i have somebody telling me that for my non-react+redux pages on the site, i should use vue.js
yet. another. view. library.
those pages will be served as static cached html+js+css from an AWS S3 box
i don't want to have to build a CMS 😃
as you said
great time to be a JS dev. worst time to be a JS dev.

@gibatronic
Copy link

TL;DR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment