Webpack 5 HMR 问题 - 无法读取未定义的 属性 'updatedChunkIds'

Webpack 5 HMR issue - Cannot read property 'updatedChunkIds' of undefined

我试图将 HMR 添加到我的 webpack 5 配置中,但出现了一个严重的错误。第一次它编译正确,但在代码更改后重新编译时 - 它因 HookWebpackError: Cannot read property 'updatedChunkIds' of undefined 而中断。如果我删除 hot: true 选项 - 一切正常。

我的配置:

const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const SVGSpritemapPlugin = require("svg-spritemap-webpack-plugin");

const path = require("path");
const fs = require("fs");

const PATHS = {
  src: path.join(__dirname, "./src"),
  dist: path.join(__dirname, "./dist"),
  icons: path.join(__dirname, "./src/assets/icons")
};

const PAGES_PUG = `${PATHS.src}/pug/`;
const PAGES_TO_CONVERT = fs
  .readdirSync(PAGES_PUG)
  .filter(filename => filename.endsWith(".pug"));

module.exports = (env, argv) => {
  const isEnvDevelopment = argv.mode === "development";
  const isEnvProduction = argv.mode === "production";

  return {
    entry: {
      app: [`${PATHS.src}/scripts/app.js`, `${PATHS.src}/scss/styles.scss`]
    },
    output: {
      path: `${PATHS.dist}`,
      filename: "./scripts/[name].[fullhash].min.js"
    },
    target: "web",
    devServer: {
      contentBase: path.join(__dirname, "dist"),
      publicPath: "/",
      open: true,
      watchContentBase: true,
      port: 8080,
      overlay: true,
      compress: true,
      hot: true
    },
    optimization: {
      splitChunks: {
        cacheGroups: {
          vendor: {
            name: "vendor",
            test: /node_modules/,
            chunks: "all",
            enforce: true
          }
        }
      }
    },
    resolve: {
      extensions: [".ts", ".js"]
    },
    devtool: isEnvDevelopment ? "eval-cheap-module-source-map" : "source-map",
    module: {
      rules: [
        {
          test: /\.pug$/,
          loader: "pug-loader",
          exclude: "/node_modules"
        },
        {
          test: /\.(scss|css)$/,
          use: [
            {
              loader: MiniCssExtractPlugin.loader
            },
            {
              loader: "css-loader",
              options: { sourceMap: true }
            },
            {
              loader: "postcss-loader",
              options: { sourceMap: true }
            },
            {
              loader: "resolve-url-loader"
            },
            {
              loader: "sass-loader",
              options: { sourceMap: true }
            }
          ],
          exclude: "/node_modules"
        },
        {
          test: /\.js$/,
          loader: "babel-loader",
          exclude: "/node_modules"
        },
        {
          test: /\.ts$/,
          loader: "ts-loader",
          exclude: "/node_modules"
        },
        {
          test: /.(jpg|jpeg|png|svg)$/,
          type: "asset/inline"
        },
        {
          test: /\.(woff(2)?|eot|ttf|otf)$/,
          type: "asset/inline"
        }
      ]
    },
    plugins: [
      new CleanWebpackPlugin(),
      ...PAGES_TO_CONVERT.map(
        page =>
          new HtmlWebpackPlugin({
            template: `${PAGES_PUG}/${page}`,
            filename: `./${page.replace(/\.pug/, ".html")}`
          })
      ),
      new MiniCssExtractPlugin({
        filename: `styles/styles.[hash].min.css`
      }),
      new CopyPlugin({
        patterns: [
          {
            from: "./src/assets/favicon",
            to: "assets/favicon",
            noErrorOnMissing: true
          },
          {
            from: "./src/assets/img",
            to: "assets/img",
            noErrorOnMissing: true
          },
          {
            from: "./src/assets/fonts",
            to: "assets/fonts",
            noErrorOnMissing: true
          }
        ]
      }),
      new SVGSpritemapPlugin("./src/assets/icons/icons-colored/**/*.svg", {
        output: {
          filename: "assets/sprites/sprites-colored/sprites.svg",
          svg4everybody: true,
          svgo: {
            plugins: [
              { inlineStyles: { onlyMatchedOnce: false } },
              { minifyStyles: true }
            ]
          }
        },
        sprite: {
          prefix: false
        }
      }),
      new SVGSpritemapPlugin(`./src/assets/icons/icons-solid/**/*.svg`, {
        output: {
          filename: "assets/sprites/sprites-solid/sprites.svg",
          svg4everybody: {
            polyfill: true
          },
          svgo: {
            plugins: [{ removeAttrs: { attrs: "(stroke|fill|style)" } }]
          }
        },
        sprite: {
          prefix: false
        }
      }),
      new ImageminPlugin({
        test: /\.(jpe?g|png|gif)$/i
      })
    ]
  };
};

我尝试删除 target 选项或将其更改为 'browserlist' - 没有效果。我还尝试删除 hot 选项并像插件部分那样初始化 HMR:

isEnvDevelopment && new webpack.HotModuleReplacementPlugin()

仍然存在同样的错误。

如果您想重现错误,您可以check all the build (dev branch)

此错误似乎已在 webpack 版本 5.27.2 中修复:https://github.com/webpack/webpack/releases/tag/v5.27.2