尝试使用 webpack ignorePlugin 从最终包中删除 'react-hot-loader'

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

react-hot-loader 文档是这样说的:

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.

尽管它是这么说的。我的目标是:

我与 react-hot-loader 相关的唯一命令在我的 App.js 文件中:

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);

如果我 运行 就像这样,我最终会在我的 app.js 转译和捆绑文件中得到以下行:

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

这是预期的。

但是如果我将 App.js 文件更改为:

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;

然后我将这一行添加到我的 webpack.config.js

webpack.config.js

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

我将使用以下行得到一个新的转译 app.js 文件:

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

注意:上一行中的第一个“***”字符实际上并不存在。我必须将它们添加到!引号中显示的感叹号。不知道为什么,但你不能用感叹号开始引用。

问题

IgnorePlugin 不是应该完全忽略 react-hot-loader 包吗?为什么它被标记为丢失?看到它甚至没有在代码中使用(因为我已经注释掉了 hot() 调用)。

Ignore Plugin 仅在包生成中排除该特定模块。但是,它不会从您的源代码中删除对该模块的引用。因此,您的 webpack 输出会抛出该错误。

绕过此错误的一种方法是使用 DefinePluginreact-hot-loader 创建虚拟存根。更多关于 here.

也就是说,如果 NODE_ENVproductionreact-hot-loader 本身会代理子项而不会发生任何变化。检查 here and here。所以在生产模式下,除了直接 returns 你的组件的 hot() 函数调用之外,没有其他事情发生。

另一个选项可以是:

// 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 />

现在由于 webpack 在构建时创建包,它知道模式是开发模式还是生产模式(更多关于 build modes) and should be able to eliminate the dead code with tree shaking and UglifyjsWebpackPlugin
确保如果您使用的是 Babel,它不会将您的代码转换为 CommonJS - 请参阅结论部分,tree shaking 页面的第 2 点。

将环境模式传递给 babel。

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