webpack配置热更新

使用webpac-dev-server自带的热更新

devServer的配置hot配置默认就是true,所以只改入口文件就好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let root: ReturnType<typeof createRoot> | null = null;

function renderApp() {
const container = document.getElementById('root');

if (!root) {
root = createRoot(container);
}

root.render(<App />);
}

// 生产环境自动移除 HMR 代码
if (process.env.NODE_ENV === 'development' && module.hot) {
module.hot.accept('./app', () => {
renderApp();
});
}

renderApp();

有可能module.hot这里会报类型错误,需要安装类型文件@types/webpack-env。
这个方案有一个缺点就是无法保存组件的状态,Webpack HMR 仅负责替换更新的模块代码,但 不感知组件状态。当模块重新加载时,组件实例会被销毁并重新创建,导致 state 重置。

react-refresh方案

这个方案的优点是可以保存组件状态,但是类组件的页面状态仍然无法保存。

安装以下依赖

1
npm install -D @pmmmwh/react-refresh-webpack-plugin react-refresh

修改webpack配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// webpack.config.js
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');

module.exports = {
mode: 'development',
target: 'web', // 必须设置为 'web' 或 'browserslist'
devServer: {
hot: true, // 启用 HMR
liveReload: false, // 关闭自动刷新
},
plugins: [
new ReactRefreshWebpackPlugin(), // 启用 React Refresh
],
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: [
'react-refresh/babel', // 注入 React Refresh 运行时
],
},
},
},
],
},
};