You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webpack+Express搭建的React项目修改文件后页面不刷新问题

热重载失效问题排查结果

一共5个核心配置错误,逐个修复即可恢复热更新能力:

    1. Webpack入口缺少热更新客户端脚本
      webpack-hot-middleware需要在入口注入客户端运行时,才能和服务端建立热更新通信连接,当前entry只配置了React入口文件,没有添加HMR客户端脚本,浏览器无法接收热更新推送。
    1. Webpack output缺少必填的publicPath配置
      server.js中读取webpackConfig.output.publicPath传给热更新中间件,但配置里未定义该字段,会导致热更新资源路径解析错误,同时webpack-dev-middleware也依赖这个字段定位内存中的编译产物。
    1. Express中间件/路由顺序错误
      静态资源服务、根路由响应逻辑写在了webpack开发中间件、热更新中间件的前面,Express按注册顺序执行中间件,开发环境下请求会优先命中磁盘上dist目录的旧静态文件,根本访问不到webpack-dev-middleware存在内存里的最新编译产物,也触发不了热更新逻辑。另外res.sendFile参数写法错误,多传参数会导致文件响应异常。
    1. webpack-dev-middleware缺少publicPath配置
      这个配置必须和webpack output里的publicPath保持一致,否则内存文件的服务路由匹配失败。
    1. React18渲染API适配问题
      当前用的是React18版本,旧的ReactDOM.render写法在HMR触发时可能出现渲染异常、状态丢失问题,推荐换成React18官方的createRoot API。

修正后的配置文件

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const webpack = require("webpack");

module.exports = {
  mode: "development",
  entry: {
    // 注入热更新客户端脚本,reload=true表示热更新失败时自动刷新页面
    app: ["webpack-hot-middleware/client?reload=true", "./src/hello.jsx"],
  },
  module: {
    rules: [
      // 新增exclude排除node_modules,大幅提升编译速度
      { test: /\.(js|jsx)$/, use: ["babel-loader"], exclude: /node_modules/ },
      { test: /\.(css)$/, use: ["style-loader", "css-loader"] },
      { test: /\.(jpg|png|jpeg)$/, use: ["file-loader"] },
      { test: /\.(html)$/, use: ["html-loader"] },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({
      template: "./src/hello.html",
      filename: "index.html",
      chunks: ["app"],
    }),
  ],
  output: {
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, "dist"),
    publicPath: "/", // 必须配置,和dev-middleware保持一致
  },
  devtool: "eval-cheap-module-source-map", // 开发环境加source-map方便调试
};

server.js

const express = require("express");
const app = express();
const path = require("path");

const PORT = process.env.PORT || 3000;
const isProd = process.env.NODE_ENV === "production";

if (!isProd) {
  const webpack = require("webpack");
  const webpackConfig = require("./webpack.config");
  const compiler = webpack(webpackConfig);
  // 开发环境的webpack中间件必须放在路由、静态服务前面
  app.use(require("webpack-dev-middleware")(compiler, {
    publicPath: webpackConfig.output.publicPath, // 必须和output.publicPath一致
  }));

  app.use(
    require("webpack-hot-middleware")(compiler, {
      noInfo: true,
      publicPath: webpackConfig.output.publicPath,
    })
  );
}

// 只有生产环境才启用磁盘静态文件服务,避免开发环境命中旧文件
if (isProd) {
  app.use(express.static(path.join(__dirname, "dist")));
}

// 路由放在中间件后面
app.get("/", (req, res) => {
  // 修正sendFile参数,传入完整文件路径
  res.sendFile(path.join(__dirname, "dist/index.html"));
});

app.listen(PORT, () => {
  console.log(`listening at localhost:${PORT}`);
});

hello.jsx(适配React18,推荐修改)

import React from "react";
import { createRoot } from "react-dom/client";
import "./hello.css";

const Hello = () => {
  return (
    <div>
      <h2>Hello React</h2>
    </div>
  );
};

const root = createRoot(document.getElementById("root"));
root.render(<Hello />);

// 热更新接收逻辑
if (module.hot) {
  module.hot.accept();
}

package.json补充说明

现有依赖没有缺失,不需要额外安装包。如果需要明确区分开发/生产环境,可以把start脚本按系统调整:

  • Windows系统:"start": "set NODE_ENV=development&&node server.js"
  • Mac/Linux系统:"start": "NODE_ENV=development node server.js"
    默认不设置NODE_ENV时也会走开发逻辑,不影响热更新生效。

所有配置修改完成后,重启node服务,再修改React组件代码即可触发热更新,无需手动刷新页面。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 07:03:32