'Trying to remove 'react-hot-loader' from final bundle using webpack ignorePlugin

This is what the react-hot-loader DOCs says:

https://www.npmjs.com/package/react-hot-loader

Note: You can safely install react-hot-loader as a regular dependency instead of a dev dependency as it automatically ensures it is not executed in production and the footprint is minimal.

Even though it says that. My goals are:

  • I want to remove react-hot-loader from my production bundle.
  • And I also want a single App.js file. That should work for DEV and PROD.

The only command that I have related to react-hot-loader is inside of my App.js file:

App.js

import { hot } from 'react-hot-loader/root';
import React from 'react';
import Layout from './Layout/Layout';

function App() {
  console.log('Rendering App...');
  return(
    <Layout/>
  );
}

export default process.env = hot(App);

If I run it just like this, I end up with the following line on my app.js transpiled and bundled file:

/* WEBPACK VAR INJECTION /(function(process) {/ harmony import / var react_hot_loader_root__WEBPACK_IMPORTED_MODULE_0__ = webpack_require(/! react-hot-loader/root */ "wSuE");

That's expected.

But if I change my App.js file to:

AppV2.js

import { hot } from 'react-hot-loader/root';  // KEEPING THE IMPORT
import React from 'react';
import Layout from './Layout/Layout';

function App() {
  console.log('Rendering App...');
  console.log(window);
  return(
    <Layout/>
  );
}

// export default hot(App); <--- COMMENTED OUT THE hot() LINE
export default App;

And I add this line to my webpack.config.js

webpack.config.js

plugins:[
  new webpack.IgnorePlugin(/react-hot-loader/)
]

I'll end up with a new transpiled app.js file with this line:

*** !(function webpackMissingModule() { var e = new Error("Cannot find module 'react-hot-loader/root'"); e.code = 'MODULE_NOT_FOUND'; throw e; }());

Note: The first '***' chars in the line above don't really exist. I had to add them in order to the ! exclation mark to be shown in the quote. Don't know why but you can't start a quote with an exclamation mark.

QUESTION

Isn't the IgnorePlugin supposed to completely ignore the react-hot-loader package? Why is it being marked as missing? See that it's not even being used on the code (since I've commented out the hot() call).



Solution 1:[1]

Ignore Plugin only excludes that particular module in bundle generation. However it will not remove the references to the module from your source code. Hence your webpack output is throwing that error.

One way of bypassing this error is to use the DefinePlugin to create a dummy stub for react-hot-loader. More on that here.

That said react-hot-loader itself proxies the children without any changes if the NODE_ENV is production. Check here and here. So in production mode apart from the hot() function call which directly returns your component, there is no other stuff that happens.

Solution 2:[2]

Another option could be:

// App.js
export default function AppFactory() {
    if (process.env.NODE_ENV === "development") {
        return hot(App);
    } else {
        return App;
    }
}

// index.js:
import AppFactory from './App';
const App = AppFactory();
// ...
<App />

Now since webpack is creating bundles at build time, it knows if the mode is development or production (more on build modes) and should be able to eliminate the dead code with tree shaking and UglifyjsWebpackPlugin.
Make sure that if you are using Babel it's not transpiling your code to CommonJS - see Conclusion section, point 2 of the tree shaking page.

Solution 3:[3]

Pass the ambient mode to babel.

"scripts": {
  "build-dev": "webpack --node-env development",
  "build-prod": "webpack --node-env production",
},

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Easwar
Solution 2
Solution 3