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

1

6

I've tried to add a HMR into my webpack 5 config and got a nasty error. First time it compiles properly, but when it comes to recompiling after code changes - it breaks with HookWebpackError: Cannot read property 'updatedChunkIds' of undefined. If I remove hot: true option - everything works properly.

My config:

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
      })
    ]
  };
};

I've tried to remove target option or change it to 'browserlist' - no effect. Also I've tried to remove hot option and init HMR like that in the plugin section:

isEnvDevelopment && new webpack.HotModuleReplacementPlugin()

and still the same error exists.

You could check all the build (dev branch) if you want to reproduce the bug.

Rustic answered 10/1, 2021 at 13:26 Comment(5)
I suspecting that it is related to one of the plugins (it probably doesn’t supports webpack 5)Mukerji
@Mukerji But it works properly without HMR option. If any plugin is incompatible with Webpack 5, bundle will simply break, won't it?Rustic
Not for sure, since HMR enables additional functionality, which may no run without it.Mukerji
I'm having the same issue, using only workbox-webpack-plugin and copy-webpack-plugin, so it looks like the latter may be the culprit.Deceptive
There is an issue opened github.com/webpack/webpack-dev-server/issues/2960Denouement
M
3

This bug appears to be fixed in webpack release 5.27.2: https://github.com/webpack/webpack/releases/tag/v5.27.2

Malraux answered 20/7, 2021 at 15:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.