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

Created on 6 Oct 2020  Β·  42Comments  Β·  Source: webpack/webpack-dev-server

  • 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
  • [x] 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.

Most helpful comment

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",

All 42 comments

Please create reproducible test repo, I think bug in webpack-dev-server

Managed to narrow it down quite a lot.

Webpack HMR bug repro.zip

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");
/******/ })()
;

@wojtekmaj Can you provide .browserlistrc?

Looks webpack-dev-server thinks it is not browser

An example is in the repro repo linked above, but I tested these and all of them broke the build for me:

Original:

Chrome >=72
Firefox >=66
IE >=11

Original but lowercase:

chrome >=72
firefox >=66
ie >=11

Thought it's maybe IE so removed and left just Chrome:

Chrome >=72

@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.

Yes, we need to fix it in webpack-dev-server, hope I will find time on it, anyway you can send a PR

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.

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.

I've pushed a pull request to fix it, can anyone with the problem try the branch with yarn's resolution? Just adding the below code to package.json and run yarn install --force

  "resolutions": {
    "webpack-dev-server": "git://github.com/chenxsan/webpack-dev-server#bugfix/fix-hmr-browserslist"
  }

Using that @chenxsan I get:

webpack_1  | > webpack-dev-server --config webpack.dev.js --trace-deprecation
webpack_1  |
webpack_1  | Error: Cannot find module '../../client/'
webpack_1  |     at Function.Module._resolveFilename (internal/modules/cjs/loader.js:668:15)
webpack_1  |     at Function.resolve (internal/modules/cjs/helpers.js:19:19)
webpack_1  |     at addEntries (/var/www/project/buildchain/node_modules/webpack-dev-server/lib/utils/addEntries.js:39:36)
webpack_1  |     at updateCompiler (/var/www/project/buildchain/node_modules/webpack-dev-server/lib/utils/updateCompiler.js:48:5)
webpack_1  |     at new Server (/var/www/project/buildchain/node_modules/webpack-dev-server/lib/Server.js:72:5)
webpack_1  |     at startDevServer (/var/www/project/buildchain/node_modules/webpack-dev-server/bin/webpack-dev-server.js:106:14)
webpack_1  |     at processOptions (/var/www/project/buildchain/node_modules/webpack-dev-server/bin/webpack-dev-server.js:166:3)
webpack_1  |     at findPort.then (/var/www/project/buildchain/node_modules/webpack-dev-server/lib/utils/processOptions.js:33:9)
webpack_1  |     at process.runNextTicks [as _tickCallback] (internal/process/task_queues.js:52:5)
webpack_1  |     at Function.Module.runMain (internal/modules/cjs/loader.js:880:11)
webpack_1  |     at internal/main/run_main_module.js:21:11
webpack_1  | npm ERR! code ELIFECYCLE
webpack_1  | npm ERR! errno 1
webpack_1  | npm ERR! [email protected] debug: `webpack-dev-server --config webpack.dev.js --trace-deprecation`
webpack_1  | npm ERR! Exit status 1
webpack_1  | npm ERR!
webpack_1  | npm ERR! Failed at the [email protected] debug script.
webpack_1  | npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
webpack_1  |
webpack_1  | npm ERR! A complete log of this run can be found in:
webpack_1  | npm ERR!     /root/.npm/_logs/2020-10-12T05_14_22_391Z-debug.log
fwt_webpack_1 exited with code 1

Using that @chenxsan I get:

webpack_1  | > webpack-dev-server --config webpack.dev.js --trace-deprecation
webpack_1  |
webpack_1  | Error: Cannot find module '../../client/'
webpack_1  |     at Function.Module._resolveFilename (internal/modules/cjs/loader.js:668:15)
webpack_1  |     at Function.resolve (internal/modules/cjs/helpers.js:19:19)
webpack_1  |     at addEntries (/var/www/project/buildchain/node_modules/webpack-dev-server/lib/utils/addEntries.js:39:36)
webpack_1  |     at updateCompiler (/var/www/project/buildchain/node_modules/webpack-dev-server/lib/utils/updateCompiler.js:48:5)
webpack_1  |     at new Server (/var/www/project/buildchain/node_modules/webpack-dev-server/lib/Server.js:72:5)
webpack_1  |     at startDevServer (/var/www/project/buildchain/node_modules/webpack-dev-server/bin/webpack-dev-server.js:106:14)
webpack_1  |     at processOptions (/var/www/project/buildchain/node_modules/webpack-dev-server/bin/webpack-dev-server.js:166:3)
webpack_1  |     at findPort.then (/var/www/project/buildchain/node_modules/webpack-dev-server/lib/utils/processOptions.js:33:9)
webpack_1  |     at process.runNextTicks [as _tickCallback] (internal/process/task_queues.js:52:5)
webpack_1  |     at Function.Module.runMain (internal/modules/cjs/loader.js:880:11)
webpack_1  |     at internal/main/run_main_module.js:21:11
webpack_1  | npm ERR! code ELIFECYCLE
webpack_1  | npm ERR! errno 1
webpack_1  | npm ERR! [email protected] debug: `webpack-dev-server --config webpack.dev.js --trace-deprecation`
webpack_1  | npm ERR! Exit status 1
webpack_1  | npm ERR!
webpack_1  | npm ERR! Failed at the [email protected] debug script.
webpack_1  | npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
webpack_1  |
webpack_1  | npm ERR! A complete log of this run can be found in:
webpack_1  | npm ERR!     /root/.npm/_logs/2020-10-12T05_14_22_391Z-debug.log
fwt_webpack_1 exited with code 1

Sorry, have no idea what's going on here. Maybe you can remove the resolution and try to edit node_modules/webpack-dev-server/lib/utils/addEntries directly? Just add a browserslist in the webTarget array. I've tested on my computer with the example code @wojtekmaj provides, it seems to be working fine with both webpack 5.0.0-rc.3 and webpack 5.

@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.

@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.

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.

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",

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.

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.

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.

Another option is to declare the browserslist in babel.config.js using the targets option of babel-preset-env as described here: https://babeljs.io/docs/en/babel-preset-env#targets

A working presets array in babel.config.js looks like this:

  presets: [
    [
      path.resolve(__dirname, 'node_modules', '@babel/preset-env'),
      {
        useBuiltIns: 'entry',
        corejs: 3,
        targets:
          'defaults, not ie < 11, last 2 versions, > 1%, iOS 7, last 3 iOS versions',
      },
    ],
    path.resolve(__dirname, 'node_modules', '@babel/preset-react'),
    path.resolve(__dirname, 'node_modules', '@babel/preset-typescript'),
  ],

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

Thank you for all you do @evilebottnawi !

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.

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!

@moxxuk Can you open an issue in webpack docs repo? We should fix it

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?

Guys and Ladies
read this: https://openbase.io/js/webpack-dev-server/versions
npm i [email protected]
devServer: { static: true }

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!

Will this fix be backported to v3 at all?

No

Any update on the new webpack-dev-server version to fix the target: web workaround?

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

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

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": {
    }
}

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

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

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.

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

target: 'web'

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 [email protected]

Tested using webpack v5.30.0.

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 πŸ˜‰

@hcorta Do you have this problem https://github.com/webpack/webpack/issues/12964?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

da2018 picture da2018  Β·  3Comments

Jack-Works picture Jack-Works  Β·  3Comments

Ky6uk picture Ky6uk  Β·  3Comments

mrdulin picture mrdulin  Β·  3Comments

wojtekmaj picture wojtekmaj  Β·  3Comments