facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
228.74k stars 46.82k forks source link

Explore encouraging users to not ship DEV mode to production #8784

Closed addyosmani closed 7 years ago

addyosmani commented 7 years ago

Do you want to request a feature or report a bug? Feature

What is the current behavior? Developers meaning to do the right thing will often accidentally ship DEV mode to production rather than PROD mode. This can have a significant impact on performance. Although DEV->PROD is a one line change, it's something React could explore encouraging.

There's great nuance here and I know that there's balance to be struck between the overall DX value this brings vs UX. Another challenge is that the change itself is trivial to make. It's unclear whether the right solution here is better defaults or stronger advocacy. Folks like @sebmarkbage have been acknowledging that this is a known issue so perhaps there's room for discussion to help improve this.

He's also noted that a switch from no warnings to DEV may require some folks to fix whole codebases which is also suboptimal. There may be an in-between solution worth talking about here however.

What is the expected behavior?

React encourages users to ship PROD mode to production rather than DEV. I would be open to a solution that is either provided at the library layer (or somehow tackled during build/bundling time by Webpack) that tries to ameliorate this.

This thread had a number of suggestions ranging from localhost detection, to alerts to injecting 'dev mode' messages to the DOM if used in a production environment. Something like this:

Alternatively, @thelarkinn was proposing that we tried to standardize on ENV configs being required to better facilitate detection of messaging like this. It's unclear which of these would be the most realistic. There are likely other ideas React core might have around how to tackle the problem.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

All recent versions.

This thread from @jordwalke prompted this issue. I think he also makes a fair point regarding benchmarks, but I care about how we can help folks ship the prod experience y'all have worked on optimizing to end customers in all it's glory.

jakearchibald commented 7 years ago

Sorry to sound like a stuck record, but console warnings don't appear to work. Eg https://code.gov.

glenjamin commented 7 years ago

Sorry to sound like a stuck record, but console warnings don't appear to work. Eg https://code.gov.

A single counter-instance shows that it's not infallible - but I don't think any approach will be.

If a console warning is able to increase awareness and reduce the number of people who mistakenly run dev mode when they shouldn't then this seems like a step in the right direction. Perfect is the enemy of good.

taion commented 7 years ago

@jakearchibald

Yes, but if code.gov's build tool were set up with hooks here, then that would have prevented the problem you're observing, at least in the context of React that uses build-time hooks for this. They are using webpack after all.

I am not saying that webpack should emit a build warning. I am saying that the right fix is that either webpack sets process.NODE_ENV for you, or that webpack just fails the build by default if you try to make a production build without appropriate production config.

s3ththompson commented 7 years ago

Wanted to quickly respond to an earlier point from @addyosmani about DevTools "violations." We're prototyping showing stronger indications of certain errors in Chrome DevTools, but this work is still quite early, and I tend to agree with @jakearchibald that showing a warning (even if it's scarier than console.warn) isn't a good enough solution.

What about defaulting React to production mode and turning on development mode if and only if NODE_ENV == 'development' or hostname is localhost / 127.0.0.1? Most developers will get correct behavior out-of-the-box and there will always be a way to manually force development mode if you really need to.

taion commented 7 years ago

Seems less than ideal to still be hitting that branch with what might be a fairly complicated conditional (since you'd need to not just fail on Node) all the time.

BTW, -p ("production" mode, which also enables minification with default settings) in webpack 2 sets NODE_ENV for users: https://webpack.js.org/guides/production-build/#node-environment-variable.

This seems quite sensible to me, and should just prevent this problem for almost everyone using webpack. Why the insistence on handling any of this at run time?

addyosmani commented 7 years ago

BTW, -p ("production" mode, which also enables minification with default settings) in webpack 2 sets NODE_ENV for users: https://webpack.js.org/guides/production-build/#node-environment-variable.

Yep. We're aware of this. @TheLarkInn from Webpack core could confirm for sure, but my understanding is that -p is not widely used in the Webpack community atm. The underlying issue here is also that if any solution is opt-in, similar to the current status quo with console.log warnings, we're unlikely to see real change for React users. We want to give folks a better change at shipping the 'fast' thing.

It's worth mentioning in passing that the lack of being able to easily detect DEV and PROD environments in Webpack (-p being insufficient) also caused us some pain over in https://github.com/webpack/webpack/issues/3216.

I am saying that the right fix is that either webpack sets process.NODE_ENV for you, or that webpack just fails the build by default if you try to make a production build without appropriate production config.

I'm up for us pursuing this but it would be a breaking change for Webpack from what I can tell. I personally feel like a runtime solution that involves a clear overlay message only displayed using a few intelligent heuristics (localhost, DevTools open etc) would cover us adequately.

That said, as we keep circling back to the Webpack process.NODE_ENV item, I'd be curious if @sokra or @TheLarkInn had any opinions on this one.

taion commented 7 years ago

My understanding differs from yours there – I believe that -p is the de facto way that most non-expert users of webpack set up production builds.

Even prominent packages use -p to generate production builds: https://github.com/ReactTraining/react-router/blob/5e69b23a369b7dbcb9afc6cdca9bf2dcf07ad432/package.json#L23 https://github.com/react-bootstrap/react-bootstrap/blob/61be58cfdda5e428d8fb11d55bf743661bb3f0b1/tools/dist/build.js#L10

It's quite uncommon to directly configure the Uglify plugin in webpack, so without -p, people would be using un-minified builds, in which case they have bigger problems.

surma commented 7 years ago

I personally feel like a runtime solution that involves a clear overlay message only displayed using a few intelligent heuristics (localhost, DevTools open etc) would cover us adequately.

I feel like this has been shot down multiple times (“It is unacceptable for a framework to inject things into the DOM”) without actually appreciating the only scenario in which this would happen.

I am totally with y’all that having to cope with a permanent message and unexpected things in the DOM constantly during development is unacceptable. What we are suggesting here, though, is a message that gets displayed if and only if DevMode gets deployed to production (enter heuristics!). An arbitrary number of checks and console messages can be built into tooling, CI and browser extensions to prevent that from happening.

But as a desperate, last resort failsafe I think a visible banner on screen is a good and appropriate solution.

KrisSiegel commented 7 years ago

displayed if and only if DevMode gets deployed to production (enter heuristics!)

So a developer will never see this message, deploy (perhaps accidentally) dev mode into production and suddenly they're seeing this new HTML being displayed on their application for all of their users to see?

That sounds more like a punishment to me. If you don't understand dev mode already and you deploy using this theoretical new version of React with the message then you're going to get a surprise and your users on the web application at the time also get to see it. I fail to see how this helps anyone but serve to embarrass the developer or company. Sure, maybe that'll get them to fix it, but that cost is too high in my opinion and lacking a bit of empathy.

But as a desperate, last resort failsafe I think a visible banner on screen is a good and appropriate solution.

The problem with this solution is that it is far too idealistic and when you're developing a framework you must focus on the reality that other companies may not have the greatest deployment policies or even the best QA (if any).

Yes, if someone deploys to dev mode in production they should be able to see it and change it quickly. Unfortunately, especially outside of the technology industry, this is simply not possible or not easy. The majority of the people commenting in here? Likely their companies have deployment processes that could cope just fine with this scenario. Google, Facebook, PlayStation, etc; all of these technology companies can handle this fine but this isn't representative of the majority of users that use React, right? (actually, do we have any statistics regarding the usage of React? Would be handy!)

Yes, yes these companies and government should change their deployment processes and policies etc etc. But the reality is this: most companies have crap deployment processes and crap to non-existent QA.

Let's take two scenarios in which I have personally experienced.

First, while working in the government, depending on branch and department, you likely have a single deployment every 3-6 months. These deployments roll up as much stuff as possible and if any piece of the entire deployment fails, everything may get rolled back. So we were using this software called OWF which, if you're unfamiliar, is like iSocial in that it displays multiple web applications in a single web application using iframes (gross, I know, but stay with me here). There was a manual configuration step in the deployment of several of our applications that failed which caused 404 and 500 errors to display in some of the iframes instead of the intended application.

Since developers typically do not have access to the system being deployed into it took many hours before we found out about any issues. At that point we had to get our boss to call someone else's boss to call their boss to tell them it didn't affect anything else so they wouldn't roll back the entire deployment. Then we had tons of paperwork and documentation to fill out before we could get anyone to redo some of the configuration several days later. Meanwhile the application sat, unable to function, during that entire period of time.

Second, when I worked in finance we had a deployment go out that inadvertently included a developer's name in place of an actual item's layout on the website (I believe he was testing something?). Anyway, it was noticed right away but in order to fix it we had to get an emergency change control through which took until much later that day. So their customers had to see this stupid banner for almost a full 8 hours before it was fixed.

My point being: there needs to be great care taken when injecting arbitrary elements into the DOM that the developer did not put there. Especially if we're talking about only displaying it in some scenarios then the first time someone sees it their going to figure out how to quickly disable it so they don't need to be bothered by it again.

addyosmani commented 7 years ago

@KrisSiegel

If you don't understand dev mode already and you deploy using this theoretical new version of React with the message then you're going to get a surprise and your users on the web application at the time also get to see it.

I was curious if your thoughts on the approach were any different if the message was only displayed while DevTools was open (i.e something that would have a low chance of being seen by production users that are not developers). Effectively an expansion of the current console.log strategy React already employs today.

KrisSiegel commented 7 years ago

I was curious if your thoughts on the approach were any different if the message was only displayed while DevTools was open (i.e something that would have a low chance of being seen by production users that are not developers). Effectively an expansion of the current console.log strategy React already employs today.

If you have dev tools open then you're probably seeing console.log messages so DOM changes seem like an unnecessary complexity to manage plus it's redundant. You could always make the React console messages larger / fancier. Maybe an ASCII React logo. Something to catch someone's attention should they happen to go in there.

Ultimately though I think someone would run into this, ask on Stackoverflow how to disable the warning, someone will post code showing them how to do it, then people will simply disable it if they run into it. Build tools are numerous and many folks that I've talked to in the past found them confusing or difficult (Babel 6's release was a "fun" time). You're going to run into a lot of people who simply never use them correctly.

At least that's my experience ¯\_(ツ)_/¯

TheLarkInn commented 7 years ago

Whew, finally caught up to the bottom of thread. Okay. I've been brainstorming this a little bit.

Webpack could force specifying NODE_ENV which React could then use to more easily avoid folks shipping DEV to PROD, but that would be a breaking change to Webpack. I'm talking to Sean now about how feasible something like that could be for Webpack 3. Keeping the React + Webpack stack beginner and perf friendly is something I know both camps care about.

This has felt like my favorite so far but I'm not 100% sold yet.

  1. So could enforce that an ENV is passed in whenever anyone runs webpack. A helpful error message states that you must provide an env variable to run webpack.

However this provides a significant bounce point for users. Not everyone is writing for a prod or dev env or even know what an env is. I will raise an issue on webpack/webpack to get feedback on this, because my gut feeling is that not everyone will want this and whether I agree or not, we have to consider the pushback.

  1. <something in-between 1 and 3 I haven't figured out yet>

  2. The webpacky solution would be to create a standalone plugin that could hook into the compiler lifecycle, check if the code is being stripped, or if an ENV is not provided, and emit a friendly warning or error of your choice.

However I can imagine the response is "But users will never know how to do that etc." Thus CRA, thus this issue right now.

We could create a new resolver pattern that will check React's (or any fw that needs it) package.json for something like below:

"webpack": {
  "plugin": "ReactEnviornmentPlugin"
}

that would automatically apply to a users compiler configuration without them needing to know or care.

Again just really brainstorming.

taion commented 7 years ago

@TheLarkInn I think the current behavior of -p in webpack 2 is sufficient, no? The only failure case is if someone sets up UglifyJsPlugin themselves and forgets to do DefinePlugin, but that seems like a far less likely case.

TheLarkInn commented 7 years ago

@taion Yes/No

-p only applies production "treatments" to your code, however we do not make any assumptions about and/nor have any knowledge of what NODE_ENV is set to. This is what brings upon the need for people to use DefinePlugin().

But I do think it is the closest "reasonable" area to guess or imply that the user is running their code in a production ENV. That would be the one area that we would want make sure the community and team is okay with.

taion commented 7 years ago

@TheLarkInn I believe this changed in v2: https://webpack.js.org/guides/production-build/#node-environment-variable

TheLarkInn commented 7 years ago

Ah sorry that's right I'm mistaken. It however it's not used frequently because people want more fine grained control over what they optimize. (Like @addyosmani mentioned)

taion commented 7 years ago

Is that really so common? When I was getting started with webpack, -p clearly seemed like the way to go. Like I referenced above, even libraries with plenty of reason to apply further tweaks still use -p.

addyosmani commented 7 years ago

We could create a new resolver pattern that will check React's (or any fw that needs it) package.json for something like below:

"webpack": { "plugin": "ReactEnviornmentPlugin" } that would automatically apply to a users compiler configuration without them needing to know or care.

@TheLarkInn if I'm reading this correctly, to trigger the resolver pattern an app's package.json would need to manually specify the ReactEnvironmentPlugin, right? Or am I misunderstanding the proposal? :)

I could imagine some resolution magic in Webpack that detects a project is using React and does the right environment switching for them, but that sounds like a tight coupling of framework-specific optimisation to a bundler and might not be as desirable.

TheLarkInn commented 7 years ago

Less that it would detect react, and more that it would detect a js modules description fields include a webpack field with a plugin. But you are right, it is very tightly coupled and not really my favorite idea either.

taion commented 7 years ago

I don't think this really gives you any guarantees unless webpack has a concept of "production" mode to figure out how to configure React – and this seems redundant given that, as discussed above, -p already does the right thing, and is what users will generally reach for when making a minified production build with webpack anyway.

gaearon commented 7 years ago

We’ve talked about this a bit more and I think there is a reasonable solution.

We’ve long considered enabling a “warning box” for React warnings in development. You can see a demo here (PR: https://github.com/facebook/react/pull/7360). It only shows up when you have warnings but they are very common during development (and should always be fixed), so presumably anyone who spent more than five minutes developing an app will see the dialog and be aware that it exists.

After this change, it will be harder to be unaware of the development mode. You’ll likely search for “how to remove the warning dialog” and learn about building for production. If you don’t, you’re likely to get some warnings deployed at some point, and your users will see them. I think that in this case people won’t blame React per se because we don’t just show the box to be obnoxious—we just do what the development mode is supposed to.

(By the way, we’ve been using a similar warning box in development at Facebook for a long time so it corresponds to how we intend React to be used.)

surma commented 7 years ago

I am really happy to see that proposal, @gaearon! It’s everything I dreamed it to be ;)

Just as an side: Maybe it’s worth considering having a link directly in the box to not require the developers to google for how to get rid of it.

gaearon commented 7 years ago

Yea, good point. We'll add something.

KrisSiegel commented 7 years ago

@gaearon I find that solution highly obnoxious; I would never want warnings to invade the DOM even during development. That serves zero purpose for the common developer and would likely be disabled in its entirely by most. The developer tools display warnings for a reason, they don't need to be invented.

I also find it troubling that DOM solutions keep cropping up with zero rebuttals to any of my prior arguments against it. If my points are to be ignored then fine, this isn't my repository so that's fair enough, but it's disheartening to see the same argument come up, people post against it, people seem for the points as there is never an argument against them, then they just come right back up. Rinse, repeat.

gaearon commented 7 years ago

While I agree about this being true about most warnings, React warnings specifically point out the bugs in your code. They are not just suggestions.

The dialog is easy to dismiss and the individual warnings are easy to snooze (in case you don't care about them for a while) but they need to be fixed.

For comparison, this is how the dialog looks in the Facebook codebase:

screen shot 2017-01-24 at 17 55 47

Thousands of engineers don’t have a problem with it and are more productive thanks to it, so we think it’s a reasonable default. To be clear, the open source version will be less shouting:

screen shot 2017-01-24 at 17 57 14

If you have suggestions about style tweaks please feel free to comment on https://github.com/facebook/react/pull/7360.

bvaughn commented 7 years ago

Adding onto what Dan said, I'm building on top of the #7360 to hook into our recently-added error logger flow. I'm currently trying out a couple of styles of toast notifications that are a little less intrusive. I'll post some screenshots and/or a Plnkr soon for feedback.

taion commented 7 years ago

Would these warnings include the "minified dev code" warning? That'd solve a lot of things quite neatly if so.

bvaughn commented 7 years ago

I don't see why it couldn't also be used for that purpose.

KrisSiegel commented 7 years ago

@gaearon

While I agree about this being true about most warnings, React warnings specifically point out the bugs in your code. They are not just suggestions.

Those should be errors or exceptions IMO. Why are they not? Exceptions force things to be corrected but a dismissible warning does not.

Thousands of engineers don’t have a problem with it and are more productive thanks to it, so we think it’s a reasonable default.

I mentioned this in a prior point but I would guess those engineers are likely better than a good 90% of people who will use the open source version. I find it the opposite of a reasonable default. There is a reason development tools have warnings; reinventing them doesn't make sense to me. It'll get disabled and never seen again.

This just looks like React is trying to do too much IMO.


Anyway, I'm just repeating my arguments that I've already said twice. If you're going to go ahead then feel free. In my opinion it's not a good business to get into. I'll just leave this short anecdote about a time when I wanted to punch some toast...

When I did government contracting we had a common library all front ends had to use. It would take errors in the console and display them as a toast pop up. No only did it get deployed to production multiple times by multiple teams but many developers saw it once then asked how to permanently disabled it. I see this as more of the same.

addyosmani commented 7 years ago

We’ve long considered enabling a “warning box” for React warnings in development. You can see a demo here (PR: #7360). It only shows up when you have warnings but they are very common during development (and should always be fixed), so presumably anyone who spent more than five minutes developing an app will see the dialog and be aware that it exists.

I really like #7360, @gaearon. It's heartening to hear support for highlighting the need to switch to PROD for deployments in the new warning box. It's nice and visual.

Adding onto what Dan said, I'm building on top of the #7360 to hook into our recently-added error logger flow. I'm currently trying out a couple of styles of toast notifications that are a little less intrusive. I'll post some screenshots and/or a Plnkr soon for feedback.

@bvaughn Looking forward to seeing more of your iterations :)

For folks who feel the warning box approach may be too intrusive, other libraries (e.g VueJS) already display DOM overlays during your dev/iteration workflow to encourage bug-fixing or slow-paths:

screen shot 2017-01-24 at 10 57 11 am

My own experience has been that while it's a minor inconvenience, these messages are more obvious than what you might see in the console. I feel Dan's right that it'll at least place more emphasis on dev mode not being something you should deploy to prod and will hopefully lead to more sites shipping "faster mode" to their end users.

After this change, it will be harder to be unaware of the development mode. You’ll likely search for “how to remove the warning dialog” and learn about building for production. If you don’t, you’re likely to get some warnings deployed at some point, and your users will see them. I think that in this case people won’t blame React per se because we don’t just show the box to be obnoxious—we just do what the development mode is supposed to.

Pajn commented 7 years ago

Those should be errors or exceptions IMO. Why are they not? Exceptions force things to be corrected but a dismissible warning does not.

While they should be fixed, I might have more urgent matters at hand. For example do I often prototype/mock up UIs and while doing that I write quick and usually sub-par code which React can warn about. While I want to fix those warnings, I don't really care until I know that I wont throw away all the code in the next hour at least. Forcing people to fix them instantly will drastically slow down experimental development.

glenjamin commented 7 years ago

For folks who feel the warning box approach may be too intrusive, other libraries (e.g VueJS) already display DOM overlays during your dev/iteration workflow to encourage bug-fixing or slow-paths:

screen shot 2017-01-24 at 10 57 11 am

Are you sure that's from Vue itself? It looks a lot like webpack build errors displayed with the error overlay from webpack-hot-middleware. If this is the case, it's subtly different because it's dev-time build tooling adding the overlay rather than a general-purpose frontend framework.

In general I'm in favour of the warning overlay, but I think it should contain explanatory text on it that says what it is, why it's there, and that it can & should be disabled as part of turning off dev mode. Behind an expando if that's a bit long - but it seems like as good a place as any to get the message across.

jquense commented 7 years ago

I dread updates like 15.2.0 with an overlay. minor bump and suddenly you have literally 100s of warnings about props being passed to DOM nodes. errors maybe, but I don't think depreciation warnings belong in such an intrusive space

bvaughn commented 7 years ago

errors maybe, but I don't think depreciation warnings belong in such an intrusive space

I don't know if this was very clearly communicated prior, but the idea regarding yellow-box warnings (#7360) was not to show all warnings (deprecation or other). Rather, certain warnings that the team deemed to be particularly important would be highlighted this way. The rest would presumably remain in the console.

At least that's my take-away from the conversation Tom and I had about this feature a week or two ago.

sebmarkbage commented 7 years ago

The prop warning in 15.2 was also a mistake IMO and not indicative of our normal M.O. We'd like to have a way to control warning levels by minor versions to avoid that.

markboyall commented 7 years ago

The main reason our team does not use the production build is because we can't run JS unit tests, since the test utils are not included.

addyosmani commented 7 years ago

First, another round of thanks to the React team (@sebmarkbage, @gaearon, @tomocchino and others) for discussing this issue with us and being so open to talking to us about performance & mobile at BlinkOn and other syncs this quarter.

Status check

Per @aweary in https://github.com/facebook/react/pull/7360, the Yellow Box solution to this particular problem has been put on hold until React’s high-prio V16 work gets completed but should still be happening. https://github.com/facebook/fbjs/pull/165 needs to land and be implemented in Fiber. A good public API for exposing hooks also needs to be crafted. Will be keeping my fingers 🤞

This problem appears to still be prevalent

Quite a few of the production apps that have come across my desk are still shipping DEV mode to production. We can see the When deploying React apps to production debug string in their builds here:

https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.js (tombraider.com) https://shared.reliclink.com/dlls/vendor-f3e016f6037eb107ffc0.live-shared.min.js (dawnofwar.com) https://d1xx3pvec9nqb7.cloudfront.net/media/js/thread.af65c1a02d15.js (thread.com) http://www.sothebys.com/etc/designs/redesigns/sothebys/redesignlibs.min.js (sothebys.com)

I'm still of the view that a pre-Yellow Box move to logging the DEV mode warning to console for the above might have some impact. Sebastian's suggestion of throwing a console error so crash reporting might pick these up was also something I felt was worth consideration.

What else can we do to move the needle here?

Better advocacy? I'm happy to commit to continuing to advocate for folks not shipping DEV mode to production, but do want to see if we can land the official solution post V16 :)

In the short-term, it looks like create-react-appis in a good place to help new projects avoid this problem.

Improvements to installation docs

For everyone else, would there be support for https://facebook.github.io/react/docs/installation.html including a clear, visible callout under the Installing React heading reminding folks to be mindful of DEV mode in production?

As a user, I don't feel there's great incentive for me to read https://facebook.github.io/react/docs/installation.html#development-and-production-versions on first glance otherwise.

Thoughts?

gaearon commented 7 years ago

The main reason our team does not use the production build is because we can't run JS unit tests, since the test utils are not included.

I’m confused about this. Are you running tests on production website? If not, what prevents you from using production build on the production website, and development build in development?

gaearon commented 7 years ago

For everyone else, would there be support for https://facebook.github.io/react/docs/installation.html including a clear, visible callout under the Installing React heading reminding folks to be mindful of DEV mode in production?

Sure. Want to send a PR?

addyosmani commented 7 years ago

Sure. Want to send a PR?

More than happy to.

jide commented 7 years ago

Maybe a word about benchmarks would be nice too to help educating those who compare perfs with react in dev mode ?

bvaughn commented 7 years ago

Makes me think the react devtools extension could be leveraged to display a notification or something obvious when opening a page using react in dev mode maybe ?

I like this idea! I put together a set of proposed icons for the devtools (see facebook/react-devtools/pull/652).

We need to decide how to detect dev vs prod React in a way that's backwards and future safe, but I've added it to the Monday meeting agenda.

gaearon commented 7 years ago

We’ve done some reasonable steps to address this problem:

I think in the future we might explore more ways to solve this problem, but for now I feel like we can move ahead without more drastic measures, and see if it helps. Thanks to everyone for the discussion.