Redux 中的热模块替换
已发表: 2022-03-11这是 Redux 应用程序中热模块替换(或 HMR)的最小示例。 工作演示代码托管在 GitHub 上。 我们只包含那些对支持 HMR 至关重要的设置,让您可以轻松地将 HMR 应用到您自己的 Redux 应用程序中。
如果您迫不及待地申请 HMR,请跳至本节,在五分钟内为您的项目设置 HMR!
运行示例
先弄脏你的手! 在运行命令启动此示例应用程序之前,请确保 Git、Node.js 和 Yarn 已正确安装在您的计算机上。
$ git clone https://github.com/Front-end-io/articles.git $ cd articles && git checkout redux-hmr $ yarn install $ yarn start
然后访问 http://localhost:3000/ 看看是否有效。
编写代码后,热模块替换能够在不完全刷新的情况下更新页面。 更重要的是,Redux 状态保持不变,而其他资源已更新到位。
热模块更换
热模块替换是 Webpack 提供的最有用的功能之一。 它允许在运行时更新各种模块,包括 JSON、CSS 和 JS 文件,而无需完全刷新。
以下是它在内部的工作方式:
- 应用程序要求 HMR 运行时检查更新。
- 运行时异步下载更新并通知应用程序。
- 然后应用程序要求运行时应用更新。
- 运行时同步应用更新。
HMR 在开发 Redux 应用程序时提高了生产力。 Redux 是 JavaScript 应用程序的可预测状态容器。 这是一个非常流行的基于 React 的最先进的框架。 根据 Redux 第一原则的定义,Redux 是一个单一的共享数据存储,其文档将其描述为“单一事实来源”。 数据存储(由reducers
更新的纯 JavaScript 对象)将随着用户对应用程序的操作而更新。 用户的每一次操作,比如点击按钮、加载后端数据等,都可能会多次更新 store。 当错误仅发生在特定的状态快照中时,修复错误并不容易。
HMR 允许我们在不重新初始化全局存储的情况下更新页面。 在 Redux 开发过程中,我们可能想在一系列操作后检查 store。 一个非常常见的情况是,只有在我们将特定(可能是复杂的)项目添加到商店后才会出现错误。 如果没有 HMR,我们必须执行以下步骤:
- 修改可能导致错误的代码。
- 刷新页面,将特定项目添加到商店。
- 如果错误仍然存在,请重复步骤 1。
如果 bug 很难找到,上面的迭代会一次又一次地重复。 在现实世界中,错误可能只有在更多操作之后才会出现。 HMR 帮助我们编译和应用修改后的代码,同时保持当前存储值不变。 我们不需要重复第2步。它提高了开发效率。
本例中的特征
我们希望保持功能最小化,只是为了演示 HMR 功能。 所以在这个应用中,我们并没有加入 React 应用中的通用特性,包括 redux-logger、react-router-redux、redux-thunk、redux-devtools 等。同时,我们只保留了一个 reducer、两个 action 和 1 个页。
我们的应用程序只在商店中保留一个计数器值。 我们只有一个名为home的页面,它显示计数器值和两个用于增加/减少计数器值的按钮。
要确认 HMR 有效,只需多次增加/减少计数器,然后修改一些代码。 例如,将标题Counter修改为Counter in store 。 然后我们会发现:
- 页面未刷新。
- 显示的计数器值未更改。
- 标题已更改为商店中的柜台。
在五分钟内设置HMR
要设置 HMR,请按照以下步骤操作。

基本库
必须安装这些库以支持 HMR:
- react-hot-loader@^4.2.0:实时编译更新React应用。
- webpack-dev-server@^3.1.4:提供 Webpack 应用程序。 根据更改更新浏览器。
ES6
如果您使用的是 ECMAScript6(现在谁不是?),您需要更多工具来实时编译 ES6。 首先,这是最小的 ES6 配置文件 .babelrc:
{ "env": { "development": { "presets": [ "react-hmre" ] } } }
为了支持实时编译,需要这个库:
- babel-preset-react-hmre@^1.1.1
Webpack.config.js
我们需要在 Webpack 配置文件 webpack.config.js 中配置 HMR。
首先,在插件部分启用 HMR 插件:
"plugins": [ … new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin(), ]
HMR 插件生成一个清单,一个列出更新模块的 JSON 文件,以及一个更新,一个包含要应用的数据的 JSON 文件。 需要注意的是,HMR 是 Webpack 提供的一个选项。 像 style-loader 这样实现 HMR 接口的加载器,通过 HMR 接收更新,然后用新代码替换旧代码。
如果我们使用 webpack-dev-server,那么我们需要在 devServer 部分打开 hot 标志:
"devServer": [ ... hot: true, ]
热重载 Redux 减速器
从 Redux 2.0.0 版本开始,reducers 不会隐式热重载,因为隐式热重载会导致一些问题。 如果您的 Redux 状态在热更新时重置为初始值,请尝试为 reducer 启用热更新:
import { createStore } from 'redux'; import rootReducer from '../reducers/index'; export default function configureStore(initialState) { const store = createStore(rootReducer, initialState); if (module.hot) { // Enable Webpack hot module replacement for reducers module.hot.accept('../reducers', () => { const nextRootReducer = require('../reducers/index'); store.replaceReducer(nextRootReducer); }); } return store; }
高级设置
更多 HMR 的高级设置,请参考 HMR API。
跑步
最后,请使用以下命令运行应用程序:
$ ./node_modules/.bin/webpack-dashboard -- webpack-dev-server
故障排除
HMR 根本不应用更改
HMR 可能会在没有任何警告的情况下静默失败。 当您更新代码并保存时,页面根本不会更新。 这可能是因为您的系统不允许您观看如此多的文件更改。
在 Ubuntu 上,您可以运行sysctl -a | grep inotify
sysctl -a | grep inotify
查看当前user.max_inotify_watches
值。 尝试通过运行来增加这个数字: sudo sysctl fs.inotify.max_user_watches=524288
。 或者,将新行fs.inotify.max_user_watches=524288
附加到文件sudo vim /etc/sysctl.conf
然后运行sudo sysctl -p /etc/sysctl.conf
以应用更改。