react项目自己配置热更新的话需要安装两个包@pmmmwh/react-refresh-webpack-plugin
和react-refresh
,这个是官方推荐的做法。下面给出一个完整demo
App.js
import React, { useState } from "react";function App() {const [count, setCount] = useState(0);return (<div><h1 onClick={() => setCount(count + 1)}>{count}</h1><div>1</div></div>);
}export default App;
index.html
<!DOCTYPE html>
<html lang="zn"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>React App</title></head><body><div id="app"></div></body>
</html>
index.js
import React from "react";
import App from "./App";
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("app"));root.render(<App></App>);
webpack.config.js
const ReactRefreshPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {entry: "./index.js",mode: "development",devServer: {static: "./dist",hot: true,},module: {rules: [{test: /\.js$/,exclude: /node_modules/,loader: "babel-loader",options: {presets: ["@babel/env", "@babel/preset-react"],plugins: [require.resolve("react-refresh/babel")], // react-refresh 添加},},],},plugins: [new ReactRefreshPlugin(),new HtmlWebpackPlugin({template: "./index.html",}),],
};
package.json
{"name": "react-hmr","version": "0.1.0","private": true,"scripts": {"start": "webpack-dev-server"},"dependencies": {"@babel/core": "^7.23.3","@babel/preset-env": "^7.23.3","@babel/preset-react": "^7.23.3","@pmmmwh/react-refresh-webpack-plugin": "^0.5.11","babel-loader": "^9.1.3","html-webpack-plugin": "^5.5.3","react": "^18.2.0","react-dom": "^18.2.0","react-refresh": "^0.14.0","webpack": "^5.89.0","webpack-cli": "^5.1.4","webpack-dev-server": "^4.15.1"}
}
之后执行npm start
,大家自行测试
这里说一下注意点,每个组件只能使用一个export
,如果有多个,热更新会失效,这点很重要。例如我们修改App.js
App.js
import React, { useState } from "react";export const delay = () => {}function App() {const [count, setCount] = useState(0);return (<div><h1 onClick={() => setCount(count + 1)}>{count}</h1><div>1</div></div>);
}export default App;
这里多加了一个export const delay
,大家可以试一下。这个时候热更新就不起作用了。
这里还解释一下为什么不用webpack的hmr,webpack不是自带hmr么,为什么还安装其他的包呢?这个问题大家可以看一下我这篇文章
还有一种方式是使用react-hot-loader
,不过react-hot-loader
已经不推荐使用了。
我们这里基于上面的代码进行改编,这里react和react-dom需要降级,把18版本降级成17版本。不然无法使用。先执行
npm i react@17.0.0 react-dom@17.0.0
npm i react-hot-loader
修改webpack.config.js配置
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {entry: "./index.js",mode: "development",devServer: {static: "./dist",hot: true,},module: {rules: [{test: /\.js$/,exclude: /node_modules/,loader: "babel-loader",options: {presets: ["@babel/env", "@babel/preset-react"],plugins: ["react-hot-loader/babel"],},},],},plugins: [new HtmlWebpackPlugin({template: "./index.html",}),],
};
修改index.js
import { hot } from "react-hot-loader/root";
import React from "react";
import App from "./App";
import { render } from "react-dom";const HotComponent = hot(App);render(<HotComponent />, document.getElementById("app"));if (module.hot) {module.hot.accept("./App", () => {render(<HotComponent />, document.getElementById("app"));});
}