webpack-dev-server: HMR/Live Reloading broken after Webpack 5 rc.0 -> rc.1 update

  • Operating System: macOS Big Sur
  • Node Version: 14.5.0
  • NPM Version: 6.14.5
  • webpack Version: 5.0.0-rc.3
  • webpack-dev-server Version: ^3.10.3
  • Browser: Chrome
  • This is a bug
  • This is a modification request

After upgrading from Webpack 5.0.0-beta.29 to 5.0.0-rc.3, I’ve noticed that HMR/Live Reloading stopped working, even though no other changes to the code were made.

I investigated by updating it step by step and here’s my outcome:

Version Works?
5.0.0-beta.29 Yes ✅
5.0.0-beta.30 Yes ✅
5.0.0-beta.31 Yes ✅
5.0.0-beta.32 Yes ✅
5.0.0-beta.33 Yes ✅
5.0.0-rc.0 Yes ✅
5.0.0-rc.1 No ❌
5.0.0-rc.2 No ❌
5.0.0-rc.3 No ❌

Code

// webpack.config.js
const webpack = require('webpack');
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');

const isProduction = process.env.NODE_ENV === 'production';
const isDevelopment = !isProduction;

const publicPath = process.env.PUBLIC_URL || '/';

module.exports = {
  mode: isProduction ? 'production' : 'development',
  bail: isProduction,
  entry: {
    src: [
      './src/index.jsx',
    ],
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath,
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        include: path.resolve(__dirname, 'src'),
        use: 'babel-loader',
      },
    ].filter(Boolean),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
  ].filter(Boolean),
  devServer: {
    historyApiFallback: true,
    hot: true,
    port: 3000,
  },
};

Expected Behavior

HMR to work on Webpack version 5.0.0-rc.1 to 5.0.0-rc.3.

Console output in 5.0.0-beta.29 to 5.0.0-rc.0:

[HMR] Waiting for update signal from WDS...
[WDS] Hot Module Replacement enabled.
[WDS] Live Reloading enabled.

…and of course, on change…

[WDS] App updated. Recompiling...
[WDS] App updated. Recompiling...
[WDS] App hot update...
[HMR] Checking for updates on the server...
[HMR] Updated modules:
[HMR]  - ./components/pages/index.jsx
[HMR] App is up to date.

Actual Behavior

HMR doesn’t on Webpack version 5.0.0-rc.1 to 5.0.0-rc.3.

Console output in 5.0.0-rc.3:

[HMR] Waiting for update signal from WDS...

…and silence after that.

I can see that Webpack is rebuilding, so I think Webpack part works fine. Refreshing the page manually also gets me the updated page. So only HMR/Live Reloading part must be broken.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 63
  • Comments: 91 (34 by maintainers)

Commits related to this issue

Most upvoted comments

Not sure if that helps, but it looks like this problem also occurs when the target is an array. For example: target: 'web' works, but target: ['web'] don’t.

Yup, the ability to set arrays as a target also came with webpack 5. Arrays are listed as a valid type in the webpack 5 docs, but not in the webpack 4 docs

EDIT: If it helps, my current fix is to specify “web” as a target when developing and “browserslist” as a target when building for production:

target: process.env.NODE_ENV === "development" ? "web" : "browserslist",

I can confirm that it works as expected with webpack 5.0.0-rc.0 but breaks with 5.0.0-rc.1 so the error is here somewhere:

https://github.com/webpack/webpack/compare/v5.0.0-rc.0..v5.0.0-rc.1

https://github.com/webpack/webpack/releases/tag/v5.0.0-rc.1

I can also confirm that if I add:

        target: 'web',

…to the base webpack config, that the latest release does indeed work.

this issue is still existing when you set browserlist in package.json

{
    "browserslist": [
        "ie >= 11",
        "chrome >= 30",
        "iOS >= 8",
        "Android >= 4"
    ],
    "keywords": [],
    "author": "",
    "license": "MIT",
    "dependencies": {
    },
    "devDependencies": {
    }
}

Interestingly, removing .browserlistrc seems to fix the issue.

So I compared src.js in both cases looking for answer and found that:

With .browserlistrc (no: when HMR not working) src.js ends with:

/******/ 	
/************************************************************************/
/******/ 	// module cache are used so entry inlining is disabled
/******/ 	// startup
/******/ 	// Load entry module
/******/ 	__webpack_require__("./src/index.jsx");
/******/ 	__webpack_require__("./node_modules/webpack/hot/dev-server.js");
/******/ })()
;

and without .browserlistrc (no: when HMR is working), src.js ends with:

/************************************************************************/
/******/ 	// module cache are used so entry inlining is disabled
/******/ 	// startup
/******/ 	// Load entry module
/******/ 	__webpack_require__("./src/index.jsx");
/******/ 	__webpack_require__("./node_modules/webpack-dev-server/client/index.js?http://localhost:3000");
/******/ 	__webpack_require__("./node_modules/webpack/hot/dev-server.js");
/******/ })()
;

Fixed in v4 branch (release will be soon, this week or first day of the next week)

@evilebottnawi looks like your diagnosis is correct, because adding target: 'web' (which overwrites the default being 'browserlist' since 5.0.0-rc.1) to Webpack config resolves the issue.

After struggling 1 day I confirm that having a browserslist file inside the root of the project breaks HMR. webpack 5.2 webpack-cli 4.1 webpack-dev-server 3.11 babel-loader 8.1.0

Everything was behaving as expected with webpack 4.

Forcing target: 'web' restores the HMR functionality, even with the browserslist file in place.

Not sure if that helps, but it looks like this problem also occurs when the target is an array. For example: target: 'web' works, but target: ['web'] doesn’t.

Is there any particular reason that this fix isn’t being backported to v3, especially since v4 is still in beta months later?

I also had a problem with the DevServer, the pages were not refreshed. I added this code and it helped me.

static: { directory: path.join(__dirname, ‘src’), watch: true, },

P.S. Maybe I didn’t understand the problem, sorry, i’m a noob. But if someone faced the same problem it helps.

I can confirm using target:web fixes the problem

Following the migration guide to webpack 5, it suggests setting target: ['web', 'es5'] which ended up breaking live reload: https://webpack.js.org/migrate/5/#need-to-support-an-older-browser-like-ie-11

Adding “target: web” fixed it for me but unfortunately means my dev environment no longer builds for IE11 - is there a way to get both working?

<w> [webpack-dev-server] “hot: true” automatically applies HMR plugin, you don’t have to add it manually to your webpack configuration.

remove:

new webpack.HotModuleReplacementPlugin({
      template: "./index.html",
    }),

It is automatically enable when hot: true (default).

static: {
      publicPath: "./build",
    },

to

static: {
      directory: "./build",
    },

Other note:

resolve: {
    // `...` extends default extensions + your add own
    extensions: [".web.js", ".ts", ".tsx", "..."],
  },

But the main problems is here:

proxy: {
      "/": {
        target: `http://localhost:${process.env.SERVER_PORT}`,
        secure: false,
      },
    },

You proxy all request to your server, you need keep, for example:

// Only HTML passed to your server
proxy: {
      "/": {
        target: `http://localhost:${process.env.SERVER_PORT}`,
        secure: false,
        bypass: function (req, res, proxyOptions) {
          if (req.headers.accept.indexOf('html') !== -1) {
            console.log('Skipping proxy for browser request.');
            return '/index.html';
          }
        },
      },
    },

Also not you need to add build/index.html - <div id="root"></div>

This problem is still actual in Webpack 5.25.1. I need to combine ES5 with live reload because there are still many enterprises who supports IE 11.

Yep @ShevchukOleg , I have webpack-dev-server version ^4.0.0-beta.0 up and working in my config, and it’s wonderful. It fixes the target: 'web' issue mentioned in this thread, too.

Thank you to @alexander-akait & the whole team for your hard work on this!

Why is this closed? This still seems to be an issue.

Setting target to web fixed it. Setting aside the non-obvious remedy – doesn’t the browserslist option basically look at the config and resolve the right target to use? If that’s the case I’d expect my target to resolve to web anyway and proceed as usual, so what’s the underlying issue here?

We were also experiencing this to still be broken in v4.0.0-beta.0 but looks to have been fully resolved in v4.0.0-beta.1 without the need to specify target: 'web'.

npm install --save-dev webpack-dev-server@4.0.0-beta.1

Tested using webpack v5.30.0.

The problem is still present in Webpack 5.30.0. Placing this in webpack.config.js solves the issue:

target: 'web'

After struggling 1 day I confirm that having a browserslist file inside the root of the project breaks HMR. webpack 5.2 webpack-cli 4.1 webpack-dev-server 3.11 babel-loader 8.1.0

Everything was behaving as expected with webpack 4.

Forcing target: 'web' restores the HMR functionality, even with the browserslist file in place.

I will add that declaring browserslist entry in your package.json also reproduces this. Doing the target workaround for now.

@xavierfoucrier here interesting case, because hot: true by default we are trying to apply hot replacement, but without watchFiles dev server doesn’t known what change in your twig template requires live reload, for this case we implement watchFiles, yes, webpack recompiling changes twig templates due twig-html-loader, in theory we can get updatedModules and check if it is empty it means nothing was changed and if compilation hash was changed it means you need to reload browser, I think we can mark this as feature

You can try beta, in near future we will do the next beta release

Heh… Just spent 2 hours trying to trace the root cause… 🤯

I would not have guessed in a million years the browser list file was the cause.

Managed to narrow it down quite a lot.

Webpack HMR bug repro.zip

The latest stable version in npm is still webpack-dev-server@3.11.2, and this issue was fixed in latest rc version:

npm i -D webpack-dev-server@4.0.0-rc.0

Looking forward to the release of the stable version of v4, thanks for your hard work 😛

@slightlyfaulty You’re right here. As of webpack v5.0.0-rc.1 https://github.com/webpack/webpack/releases/tag/v5.0.0-rc.1, the target defaults to browserslist if you have browserslist in your project. But webpack-dev-server is not updated yet to follow that change. I think that’s why client parts are not included, resulting no socket connected to the server to watch updates.

I too am experiencing this issue, which renders HMR inoperative with webpack 5, though I’m using @babel/preset-env rather than .browserlistrc.

But the symptoms are the same, everything builds, but this is all that is output in the console:

[HMR] Waiting for update signal from WDS...

I did confirm, however, that rolling back to:

        "webpack": "5.0.0-beta.29",

causes it to work again as expected:

[HMR] Waiting for update signal from WDS...
index.js:48 [WDS] Hot Module Replacement enabled.
index.js:52 [WDS] Live Reloading enabled.

use cnpm install , resolve.symlinks: false, make it happen. You can see this troubleshooting.html#symbolic-links-in-node-modules

If your requests are overlapping, i.e. you have /public/image.png for main server and /public/image.png for dev server, hard to say what is the better for you, I think you need handle only html based requests

@alexander-akait worked like a charm! Thank you very much for your help! I am very grateful

@xavierfoucrier yep, I will ping you if will need more information (but I have local version)

@myou11 this https://webpack.js.org/configuration/other-options/#ignorewarnings, ideally you should not have warnings at all or control them by filtering

@xavierfoucrier sorry for delay, I got sick covid, but I’m already better, I’ll see tomorrow

Feel free to ping me

oh, maybe you have loader or plugin for generating or something else, if you provide reproducible step I will say you what is wrong

Also:

contentBase: [
        path.join(__dirname, 'src'),
        path.join(__dirname, 'wds'),
      ],

is invalid, static.directory: [path.join(__dirname, 'src'), path.join(__dirname, 'wds')] is valid, but you don’t need to watch src, because webpack already reloads them when you do changes, for additional files (i.e. you don’t have import/@import/etc in your files you can use watcFiles, glob is supported)

In case it helps somebody: in our case (react app) live reloading stopped working after updating from webpack v4.30.0 to v5.30.0. After some investigations, we found that the react-hot-loader config was causing the issue, and that removing it from the project brings the reloading functionality back, loosing the Hot Reload though 😕.

Still missing some further investigations to properly identify the exact cause of the problem.

Important to mention that @gaearon has deprecated react-hot-loader, and they are moving towards a webpack plugin, still experimental: https://github.com/pmmmwh/react-refresh-webpack-plugin/

Hope that helps 😉

@rnnyrk the beta works wonderfully, you can see it in use here: https://github.com/nystudio107/annotated-webpack-config/tree/webpack-5

Not sure if that helps, but it looks like this problem also occurs when the target is an array. For example: target: 'web' works, but target: ['web'] doesn’t.

According to docs, “Although webpack does not support multiple strings being passed into the target property, you can create an isomorphic library by bundling two separate configurations…”

So really, using an array just breaks it, although there is no build warning to say that arrays are not accepted in the for the target attribute.

Glad I saw your comment, I was searching for hours!

Not sure if that helps, but it looks like this problem also occurs when the target is an array. For example: target: 'web' works, but target: ['web'] don’t.

Yup, the ability to set arrays as a target also came with webpack 5. Arrays are listed as a valid type in the webpack 5 docs, but not in the webpack 4 docs

EDIT: If it helps, my current fix is to specify “web” as a target when developing and “browserslist” as a target when building for production:

target: process.env.NODE_ENV === "development" ? "web" : "browserslist",

Removing the target property from webpack.config.js also works fine for me for development purpose. As you said we can later add the target property when we are building for production.

@chenxsan’s fix works for me.

Seems this issue happens when you have a browserslist entry in your package.json. Modules from ./node_modules/webpack-dev-server/client/ are not included in the output bundle at all. After removing browserslist, they are included correctly.