react项目自行配置热更新
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"));
});
}