All the assets from react-hot-loader seems to bundle in production builds. I might have misinterpreted it but they should be omitted right?
Production build without ´redbox-react´, react-proxy etc
´redbox-react´, react-proxy get bundled in production build

React Hot Loader version: v3.0.0-beta.7
Run these commands in the project folder and fill in their results:
node -v: 8.1.0npm -v: 5.0.3Then, specify:
https://github.com/alexandernanberg/minimal-react-boilerplate
In webpack.config.js add webpack-bundle-analyzer again, which is currently out commented
Run yarn build and look at the outout from the bundle analyzer
Add this to your configuration:
https://webpack.js.org/guides/production/#node-environment-variable
plugins:[
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
Added that to my webpack config but I still seem to get the dependencies in my bundle. Anyone else seeing this as well or am I doing something wrong in my config?
@alexandernanberg I am having the same issue on my production bundle. Even thou I've the NODE_ENV set to production, it seems like react-hot-loader is bundling its dependencies (like the redbox-react).
I have the same issue .
I have add
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
in my webpack production config ,and use cross-env to set the NODE_ENV=production
Having the same issue here. A temporary solution would be to have two entry files, one for production and one for dev (hot reloading):
entryProd.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(<App />, document.getElementById("root"));
entryDev.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import { AppContainer } from "react-hot-loader";
import App from "./App";
const render = Component => {
ReactDOM.render(
<AppContainer>
<Component />
</AppContainer>,
document.getElementById("root")
);
};
if (module.hot) { module.hot.accept("./App", () => { render(App); }); }
In Webpack config:
entry: {
"app": process.env.NODE_ENV !== "production"
? ["react-hot-loader/patch", "./src/_frontend/entryHot.tsx"]
: ["./src/_frontend/entryProd.tsx"],
},
Obviously not ideal if your entry files contain a lot of other logic (can try put that into a common file required in both maybe), but a way forward for now at least.
I have resolve this issue,while I update all packages and resolve it
https://github.com/bestsuperdev/react-less-boilerplate2
windows10
node v8.1,3
npm v5.0.3
I am also having this issue and would prefer not to have two entry files for each of my applications.
@alexanderchr I believe the issue is that you've got react-hot-loader/patch as part of your entry for both your dev and prod builds in your webpack.config.js. You should not include it in your prod build, so really that line should be conditional. Hopefully that resolves your issue (and others).
I'm seeing this too — I've got new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }) set in my production webpack config file, and only specify react-hot-loader/patch as an entry in my development webpack config file.
What's the reason JSON.stringify('production') is used? It seems redundant.
Same issue for me. I would like to not have two entry points. Any suggestions?
Maybe it will be helpful. I had the same issue and it was because in my .babelc was plugin
"react-hot-loader/babel". After I removed this list it's fixed. I needed it just for building project and not developing so it's okay for me. I think it's question about production .babelrc file.
I'm not using the babel plugin and still experience this issue. My only solution currently is to create separate dev and prod entry points.
To close this issue and resume, add to your Webpack config:
plugins:[
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
And then don't forget to bundle with the correct environment:
NODE_ENV=production webpack
@neoziro can you answer the question I have above? Why not just this?
plugins:[
new webpack.DefinePlugin({
'process.env.NODE_ENV': 'production'
})
]
@alasdairhurst From https://webpack.js.org/plugins/define-plugin/
Note that because the plugin does a direct text replacement, the value given to it must include actual quotes inside of the string itself. Typically, this is done either with either alternate quotes, such as '"production"', or by using JSON.stringify('production').
In your case you could use '"production"', but that could confuse somebody
@alasdairhurst you can do this if you use two separated Webpack config, one for development and one for production. It depends from your configuration. Setting NODE_ENV to production even in development will disable React warnings and React Hot Loader.
Also as mentioned by @montogeek, you have to add quotes.
@alexandernanberg Do you know the root cause and fix that?
@starandtina Not sure, my guess is that some module accidentally broke tree shaking or was not reading the env variable correctly. I've not seen this problem for a while now though
@alexandernanberg Thanks! I had removed RHL in order to avoid the issue. :)
If someone having this issue, just open your bundle source code.
Try to find https://github.com/gaearon/react-hot-loader/blob/master/src/patch.js, it must look like
/* eslint-disable global-require */
if (true) {
module.exports = __webpack_require__("./node_modules/react-hot-loader/lib/patch.prod.js");
} else {
module.exports = require('./patch.dev');
}
After uglify it will look like
function(e,o,s){"use strict";e.exports=s("./node_modules/react-hot-loader/lib/patch.prod.js")}
If NOT - that is the issue. Webpack does not reduce !module.hot || process.env.NODE_ENV === 'production' to the true of false and inject both version of a patch file.
PS: And the first piece of code I've got from debug __build__. As long module.hot is not defined
PPS: Tree shaking is not defined for commonjs(require) modules. You need dead code elimination.
PPPS: I've used NamedModulesPlugin to name modules.
Be sure to not include new webpack.HotModuleReplacementPlugin() in production.
To do that simply:
plugins: [
...(process.env.NODE_ENV !== 'production' ? [new webpack.HotModuleReplacementPlugin()] : []),
],
And to have this plugin:
plugins:[
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
]
Last step, be sure to build with the correct environment:
NODE_ENV=production webpack
Still have the issue.
cross-env NODE_ENV=production npm run babel is ok
@ganxunzou nope, doesn't work for me, still have the issue,
This code is added by react-hot-loader/babel.
In my case I solved this by conditionally adding/removing the babel plugin depends on the ENV.
IMHO this behaviour should be changed, and if babel plugin detects production environment it should simply not load.
It does it. __if__ you set env before the build.
See this PR - https://github.com/gaearon/react-hot-loader/pull/1119/files
Ah, sorry. OK, makes sense now. Didn't read the sources, just saw a bunch of code there and assumed it is similar to the dev one...
I have the same problem. Hot load mode is not used in both development mode and production mode.
In doc, when the mode is set production Sets process.env.NODE_ENV on DefinePlugin to value production.
So I think we don't need set process.env.NODE_ENV.
But how can I remove the __REACT_HOT_LOADER__ code?

That’s babel plugin, and by a some reason it thinks it’s dev time.
This code is added by
react-hot-loader/babel.In my case I solved this by conditionally adding/removing the babel plugin depends on the ENV.
IMHO this behaviour should be changed, and if babel plugin detects production environment it should simply not load.
did the same and it works! thanks
as an example here is my .babelrc.js
module.exports = api => {
const plugins = ["@babel/plugin-syntax-dynamic-import"];
// inject react-hot-loader babel plugin in development only
if (api.env("development")) {
plugins.unshift("react-hot-loader/babel");
}
return {
presets: [
[
"@babel/preset-env",
{
modules: false,
useBuiltIns: "usage"
}
],
"@babel/preset-react"
],
plugins
};
};
and here is my relevant part in webpack.config.js
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: "babel-loader",
exclude: /node_modules/
}
]
}
this is how I run my build process in package.json:
"scripts": {
"start": "webpack-dev-server --hot --env development"
}
I have found the reason that in my project I have import third part UI component. They bundle incorrectly
@bboydflo Your solution worked for me too, with a minor adjustment. The api.env call in the babel config wasn't picking up on the correct environment, just "development". In case anyone runs into a similar scenario, I had to do the following:
webpack.config.js: module.exports = env => ({ // configmode based on the env value (since webpack only supports none, development and production:// webpack.config.js
mode: env === "production" ? env : "development"
envName based on the webpack env, letting this pass through as you may have other environment names in your babel config e.g. test:// webpack.config.js
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: { envName: env },
},
],
},
package.json scripts to set the env flag:// package.json
"start": "webpack-dev-server --env development",
"build": "webpack --env production",
Also do not use the webpack.HotModuleReplacementPlugin for your production build, this appeared to be root cause for all that code added in the first place.
I haven't written against React for some time, thus revisiting webpack setup for all-things-react.
As this closed post comes high in search for current state for excluding react-hot-loader in nondevelopment, I'll give my 2 cents how to exclude any react-hot-loader stuff when not on development tier without having to maintain separate configuration files.
Count to four according to docs.
_.babelrc.js_
Add react-hot-loader/babel plugin.
_webpack.front.config.js_
react-hot-loader/patch in entry and @hot-loader/react-dom in aliases.
Parts of webpack config
// ...
const development = process.env.NODE_ENV === 'development';
const testing = process.env.NODE_ENV === 'testing';
const staging = process.env.NODE_ENV === 'staging';
const production = process.env.NODE_ENV === 'production';
const devServerRunning = !!process.env.WEBPACK_DEV_SERVER;
// ...
entry: {
index: [
'react-hot-loader/patch',
// ... any other stuff
path.resolve(__dirname, 'src/index.js')
]
},
// ...
resolve: {
// ...
alias: {
// ...
'react-dom': '@hot-loader/react-dom'
}
// ...
}
// ...
config.devServer = {
// ...
hot: true,
// ...
};
// ...
if (development && devServerRunning) {
config.plugins.push(new webpack.HotModuleReplacementPlugin());
}
// ...
config.plugins.push(new webpack.DefinePlugin({
'process.env': {
NODE_ENV: (development) ? JSON.stringify('development') : JSON.stringify('production'),
BROWSER: true
},
__CLIENT__: true,
__SERVER__: false,
__DEVTOOLS__: development,
__DEV__: development,
__PROD__: !development,
__DEVELOPMENT__: development,
__TESTING__: testing,
__STAGING__: staging,
__PRODUCTION__: production
}));
// ...
_App.js_
Export component as hot
'use strict';
import React, {Component} from 'react';
import {hot} from 'react-hot-loader/root';
class App extends Component {
constructor (props) {
console.log('App constructor');
super(props);
this.state = {myValue: 1};
this.onClickHandler = this.onClickHandler.bind(this);
}
onClickHandler () {
this.setState({myValue: this.state.myValue + 1});
}
render () {
console.log('App render');
const {myValue} = this.state;
return (
<div
onClick={this.onClickHandler}
className="template-component"
>
{`I am App and this is my value: ${myValue}`}
</div>
);
}
}
export default hot(App);
_index.js_
/* global __DEVELOPMENT__ */
'use strict';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './Containers/App/App.js';
ReactDOM.render(
<App />,
document.querySelector('.app')
);
if (__DEVELOPMENT__) {
console.log('I\'m in development!');
window.React = React;
}
When building setup above for nondevelopment tier bundle will hold
react-hot-loader/dist
react-hot-loader/root.js
react-hot-loader/patch.js
Simple edit in webpack config that conditionally excludes entry and switches back to nonpatched react-dom
_webpack.front.config.js_
// ...
entry: {
index: [
(development) ? 'react-hot-loader/patch' : null,
// ... any other stuff
path.resolve(__dirname, 'src/index.js')
].filter((e) => e !== null)
},
// ...
resolve: {
// ...
alias: {
// ...
'react-dom': (development) ? '@hot-loader/react-dom' : 'react-dom'
}
// ...
}
// ...
yields that nondevelopment tier bundle will hold now only
react-hot-loader/root.js
In order to get rid of that last one bit one has to switch from hot export to hot import, as conditional imports (requires) are possible which in conjunction with TerserPlugin / dead code stripping makes this work.
Thus avoiding react-hot-loader/root HOC in root component and conditionally wrapping it in react-hot-loader/AppContainer.
_App.js_
'use strict';
import React, {Component} from 'react';
class App extends Component {
constructor (props) {
console.log('App constructor');
super(props);
this.state = {myValue: 1};
this.onClickHandler = this.onClickHandler.bind(this);
}
onClickHandler () {
this.setState({myValue: this.state.myValue + 1});
}
render () {
console.log('App render');
const {myValue} = this.state;
return (
<div
onClick={this.onClickHandler}
className="template-component"
>
{`I am App and this is my value: ${myValue}`}
</div>
);
}
}
export default App;
_index.js_
/* global __DEVELOPMENT__ */
'use strict';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './Containers/App/App.js';
if (__DEVELOPMENT__ && module.hot) {
const AppContainer = require('react-hot-loader').AppContainer;
const renderHot = (Component) => {
ReactDOM.render(
<AppContainer>
<Component />
</AppContainer>,
document.querySelector('.app')
);
};
renderHot(App);
module.hot.accept('./Containers/App/App.js', () => {
renderHot(App);
});
}
else {
const renderCold = (Component) => {
ReactDOM.render(
<Component />,
document.querySelector('.app')
);
};
renderCold(App);
}
if (__DEVELOPMENT__) {
console.log('I\'m in development!');
window.React = React;
}
Tadā.
Most helpful comment
Added that to my webpack config but I still seem to get the dependencies in my bundle. Anyone else seeing this as well or am I doing something wrong in my config?