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 文件,而無需完全刷新。

以下是它在內部的工作方式:

  1. 應用程序要求 HMR 運行時檢查更新。
  2. 運行時異步下載更新並通知應用程序。
  3. 然後應用程序要求運行時應用更新。
  4. 運行時同步應用更新。

模塊熱更換圖

HMR 在開發 Redux 應用程序時提高了生產力。 Redux 是 JavaScript 應用程序的可預測狀態容器。 這是一個非常流行的基於 React 的最先進的框架。 根據 Redux 第一原則的定義,Redux 是一個單一的共享數據存儲,其文檔將其描述為“單一事實來源”。 數據存儲(由reducers更新的純 JavaScript 對象)將隨著用戶對應用程序的操作而更新。 用戶的每一次操作,比如點擊按鈕、加載後端數據等,都可能會多次更新 store。 當錯誤僅發生在特定的狀態快照中時,修復錯誤並不容易。

HMR 允許我們在不重新初始化全局存儲的情況下更新頁面。 在 Redux 開發過程中,我們可能想在一系列操作後檢查 store。 一個非常常見的情況是,只有在我們將特定(可能是複雜的)項目添加到商店後才會出現錯誤。 如果沒有 HMR,我們必須執行以下步驟:

  1. 修改可能導致錯誤的代碼。
  2. 刷新頁面,將特定項目添加到商店。
  3. 如果錯誤仍然存在,請重複步驟 1。

如果 bug 很難找到,上面的迭代會一次又一次地重複。 在現實世界中,錯誤可能只有在更多操作之後才會出現。 HMR 幫助我們編譯和應用修改後的代碼,同時保持當前存儲值不變。 我們不需要重複第2步。它提高了開發效率。

糾正錯誤並不意味著您必須使用 HMR 重新啟動應用程序。

注意:在某些情況下,代碼修改可能會影響當前存儲值。 在這種情況下,HMR 會警告您重新加載整個頁面。

本例中的特徵

我們希望保持功能最小化,只是為了演示 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以應用更改。