本文概述
这是Redux应用程序中热模块更换(或HMR)的最小示例。可用的演示代码托管在GitHub上。我们仅包含支持HMR所必需的那些设置, 从而使你轻松在自己的Redux应用程序中应用HMR。
如果你迫不及待要申请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运行时检查更新。
- 运行时异步下载更新并通知应用程序。
- 然后, 应用程序要求运行时应用更新。
- 运行时将同步应用更新。
开发Redux应用程序时, HMR可以提高生产率。 Redux是JavaScript应用程序的可预测状态容器。这是一个非常流行的基于React的最新框架。根据Redux的第一个原理的定义, Redux是一个单一的共享数据存储, 其文档将其描述为”单一事实来源”。数据存储(由reducers更新的普通JavaScript对象)将随着用户在应用程序上的操作而更新。每个用户操作, 例如单击按钮, 加载后端数据等, 都可能会多次更新存储。如果仅在特定状态快照下发生错误, 修复错误就不容易了。
HMR允许我们更新页面而无需重新初始化全局存储。在Redux开发期间, 我们可能要经过一系列操作来检查商店。一个非常常见的情况是, 只有在我们向商店添加了特定(可能是复杂的)商品后, 才会出现错误。没有HMR, 我们必须执行以下步骤:
- 修改可能导致该错误的代码。
- 刷新页面, 将特定项目添加到商店。
- 如果错误仍然存在, 请重复步骤1。
如果难以发现错误, 将一次又一次重复上述迭代。在现实世界中, 该错误可能仅在进行更多操作后才会出现。 HMR帮助我们编译和应用修改后的代码, 同时保持当前存储值不变。我们不需要重复步骤2。它可以提高开发效率。
注意:在某些情况下, 代码修改可能会影响当前存储值。在这种情况下, HMR将警告你重新加载整个页面。
本示例中的功能
我们只想演示HMR功能, 就希望使该功能保持最小。因此, 在此应用程序中, 我们没有在React应用程序中合并通用功能, 包括redux-logger, react-router-redux, redux-thunk, redux-devtools等。同时, 我们仅保留一个reducer, 两个action和1页。
我们的应用程序仅在商店中保留计数器值。我们只有一页称为home的页面, 其中显示计数器值和两个用于增加/减小计数器值的按钮。
要确认HMR是否有效, 只需多次增加/减少计数器, 然后在src / js / components / home.js处修改一些代码即可。例如, 在商店中将标题”计数器”修改为”计数器”。然后我们会发现:
- 该页面未刷新。
- 显示的计数器值未更改。
- 标题已更改为商店中的柜台。
在五分钟内设置HMR
要设置HMR, 请按照下列步骤操作。
基本图书馆
必须安装以下库以支持HMR:
- [电子邮件保护] ^ 4.2.0:实时编译和更新React应用程序。
- [电子邮件保护] ^ 3.1.4:提供Webpack应用。根据更改更新浏览器。
ES6
如果你使用的是ECMAScript6(如今不是谁), 则需要更多工具来实时编译ES6。首先, 这是最小的ES6配置文件.babelrc:
{
"env": {
"development": {
"presets": [
"react-hmre"
]
}
}
}
为了支持实时编译, 需要以下库:
- [电子邮件保护] ^ 1.1.1
Webpack.config.js
我们需要在Webpack配置文件webpack.config.js中配置HMR。
首先, 在”插件”部分中启用HMR插件:
"plugins": [
…
new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin(), ]
HMR插件生成清单(Manifest), 列出更新模块的JSON文件, 以及更新(Update), 包含要应用的数据的JSON文件。需要注意的是, HMR是Webpack提供的一个选项。实现HMR接口的诸如样式加载器之类的加载器会通过HMR接收更新, 然后用新代码替换旧代码。
如果使用webpack-dev-server, 则需要在devServer部分中打开hot标志:
"devServer": [
...
hot: true, ]
热装Redux Reducer
从Redux版本2.0.0开始, reducer不会隐式热加载, 因为隐式热重新加载会引起一些问题。如果在热更新时将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查看当前user.max_inotify_watches值。尝试通过运行以下命令增加该数目:sudo sysctl fs.inotify.max_user_watches = 524288。或者, 在文件sudo vim /etc/sysctl.conf中追加新行fs.inotify.max_user_watches = 524288, 然后运行sudo sysctl -p /etc/sysctl.conf来应用更改。