webpack-dev-server icon indicating copy to clipboard operation
webpack-dev-server copied to clipboard

HMR not working with multiple entries

Open slightlyfaulty opened this issue 5 years ago • 55 comments
trafficstars

  • Operating System: Linux
  • Node Version: 14.14.0
  • NPM Version: 6.14.7
  • webpack Version: 5.2.0
  • webpack-dev-server Version: 3.11.0
  • Browser: Google Chrome
  • [x] This is a bug
  • [ ] This is a modification request

Code

https://github.com/slightlyfaulty/webpack-hmr-multi-entry-repro

// webpack.config.js
...
entry: {
  first: ['./src/first.js', './src/first.css'],
  second: ['./src/second.js', './src/second.css'],
},
...

Expected Behavior

After starting the dev server, hot module replacement should work for all JS and CSS files from all webpack entries.

Actual Behavior

Hot module replacement doesn't work for all entries. Only files from the second entry are hot reloaded when changed. Files from the first entry do not get hot reloaded when changed.

For Bugs; How can we reproduce the behavior?

  1. Clone repro then yarn && yarn start
  2. Open http://localhost:8080/
  3. Change src/first.js and src/first.css - notice they are not hot reloaded
  4. Change src/second.js and src/second.css - notice they are hot reloaded

slightlyfaulty avatar Oct 22 '20 21:10 slightlyfaulty

Upon further testing, it seems that HMR only works for the last loaded JS bundle on the page. HMR will not work for any JS bundle loaded before it. The order of the entries in webpack.config.js does not matter.

slightlyfaulty avatar Oct 22 '20 22:10 slightlyfaulty

@slightlyfaulty setting optimization.runtimeChunk: "single" fixed the problem for me.

MohsenElgendy avatar Nov 09 '20 17:11 MohsenElgendy

Thanks for the tip @MohsenElgendy, but it's still not really ideal as you need to then load the runtime chunk alongside your other bundles. Webpack 4 handled embedding the runtime in multiple bundles at the same time no problem.

slightlyfaulty avatar Nov 09 '20 17:11 slightlyfaulty

I can also confirm optimization.runtimeChunk: "single" fixed the problem for me handling multiple bundles.

webpack.dev.config

module.exports = () => {
  const config = {
    mode: 'development',
    // Map your compiled code back to your original source code.
    devtool: 'inline-source-map',
    target: 'web',
    output: {
      filename: '[name].js',
      // specify chunck path for code splitted files
      chunkFilename: '[name].js',
    },
    devServer: {
      historyApiFallback: true,
      contentBase: path.resolve(__dirname, '../dist'),
      publicPath: '/',
      open: true,
      compress: true,
      hot: true,
      port: 8080,
    },
    plugins: [
      new ESLintPlugin({
        extensions: ['js', 'ts'],
      }),
      new StylelintPlugin(),
      new webpack.HotModuleReplacementPlugin(),
    ],
    optimization: {
      // don't minimize so we can debug
      minimize: false,
      /*
        The value 'single' instead creates a runtime file to be shared for all generated chunks.
        https://github.com/webpack/webpack-dev-server/issues/2792
      */
      runtimeChunk: "single",
    },
  };
  return merge(common('development'), config);
};

webpack.common.js

module.exports = (env) => {
  const isProduction = env === 'production';

  ...

  return {
    target: 'web',
    entry: {
      main: [
        './src/js/index.js',
        './src/ts/index.ts',
      ],
      // webpack code splitting example file
      examples: [
        './src/js/examples.js',
      ],
    },
    output: {
      path: path.join(__dirname, '../dist'),
      publicPath: '/',
    },

  ...

};

waldronmatt avatar Nov 11 '20 16:11 waldronmatt

Same issue here, setting optimization.runtimeChunk: "single" fixed the problem for me as well, but I would consider this a workaround for a bug that should be fixed anyway. This certainly worked before.

uxsoft avatar Nov 20 '20 12:11 uxsoft

I think it fixed in v4 branch, you can try it

alexander-akait avatar Nov 20 '20 13:11 alexander-akait

@evilebottnawi Can't test properly because it seems writeToDisk has been removed in v4 for some reason?

Initial compilation also takes much longer than the regular build time now. Over 6 seconds compared to <2 seconds for regular build. On v3 it only takes about 2.2 seconds for the initial dev server compilation.

slightlyfaulty avatar Nov 25 '20 13:11 slightlyfaulty

It was not removed, it was moved to dev: { writeToDisk: true }

alexander-akait avatar Nov 25 '20 14:11 alexander-akait

There is no changes between v3 and v4 in perf

alexander-akait avatar Nov 25 '20 14:11 alexander-akait

It was not removed, it was moved to dev: { writeToDisk: true }

Aha.. that's working now, but can confirm this bug is still present. Only the last loaded bundle in the document hot reloads properly. Bundles from other entries do not hot reload at all.

Also had to explicitly disable liveReload, otherwise it live reloaded the page after every change, even though hot is enabled.

There is no changes between v3 and v4 in perf

Evidence would suggest otherwise sir. Will open an issue after release of v4 if it persists.

slightlyfaulty avatar Nov 25 '20 17:11 slightlyfaulty

@slightlyfaulty Please create reproducible test repo, it should work

alexander-akait avatar Nov 26 '20 11:11 alexander-akait

@alexander-akait Sure. https://github.com/slightlyfaulty/webpack-hmr-multi-entry-repro

  1. yarn && yarn start - Open http://localhost:8080/
  2. Change src/first.js and src/first.css - notice they are not hot reloaded, and there are some errors in the browser console
  3. Change src/third.js and src/third.css - notice they are hot reloaded correctly, because they're loaded last in the page

slightlyfaulty avatar Nov 26 '20 17:11 slightlyfaulty

Is there a reason to avoid multiple entry points / bundles, because I'm surprised that not a ton of people are also reporting this bug? I know I need to have them. One example is I need certain things loaded in my site header and the rest at the end of the body.

One thing to note / add to the error report from @slightlyfaulty, I noticed all the console messages come in as warnings not errors, even though indeed HMR spews out a tons of warning messages like so:

[HMR] Update failed: Loading hot update chunk site_header failed.
(missing: https://localhost:3018/dist/site_header.3fb54bab211f3a92bb04.hot-update.js)
loadUpdateChunk/<@https://localhost:3018/dist/site_header.bundle.js:10391:26

onetrev avatar Dec 06 '20 09:12 onetrev

same issue.

andywang646691 avatar Dec 10 '20 06:12 andywang646691

same issue.

wangmeijian avatar Dec 23 '20 06:12 wangmeijian

Any news on this? I don't want to have to downgrade several packages to get it to work, and this is really slowing down development...

Connum avatar Jan 04 '21 11:01 Connum

Exactly the same problem and same warnings as @onetrev on webpack 5.9.18 On 4.46 HMR for multiple entries works fine.

pixelhuh avatar Jan 27 '21 05:01 pixelhuh

I also encountered this issue with multiple entries. However setting optimization.runtimeChunk: "single" didn't work. I'm using multiple HtmlWebpackPlugins to serve the entries as solo applications. What is the best step for now? Move back to [email protected]?

koen-dev avatar Feb 25 '21 20:02 koen-dev

Also encountered this issue. Setting optimization.runtimeChunk: "single" is not working for me. I need to output my code as library. Using [email protected] and [email protected]. Current working solution is to set hot: false and do a full page reload for every change.

ghost avatar Mar 03 '21 07:03 ghost

Please test https://github.com/webpack/webpack-dev-server/releases/tag/v4.0.0-beta.1, we will speed up releases, to be stable at the end of month

alexander-akait avatar Mar 23 '21 17:03 alexander-akait

@alexander-akait Nope no change to the issue.

https://github.com/webpack/webpack-dev-server/issues/2792#issuecomment-734406486

slightlyfaulty avatar Mar 23 '21 23:03 slightlyfaulty

@slightlyfaulty Found solution:

<script type="text/javascript" src="dist/runtime.js"></script>
<script type="text/javascript" src="dist/first.js"></script>
<script type="text/javascript" src="dist/second.js"></script>
<script type="text/javascript" src="dist/third.js"></script>
optimization: {
  runtimeChunk: 'single'
},

alexander-akait avatar Mar 25 '21 15:03 alexander-akait

@alexander-akait That solution has already been posted before.

It's more of a workaround than a solution though don't you think? Since it worked fine in Webpack 4 without needing to generate and load a runtime bundle.

slightlyfaulty avatar Mar 25 '21 15:03 slightlyfaulty

@slightlyfaulty Here are multi entries on one page... so we have multiple __webpack_require__ with HMR, each __webpack_require__ known only about own modules and HMR status, when we get update we will run multiple of them, so you can see [HMR] Update failed: ChunkLoadError: Loading hot update chunk first failed. and [HMR] Update failed: ChunkLoadError: Loading hot update chunk second failed.

alexander-akait avatar Mar 25 '21 16:03 alexander-akait

Give me time to look at this deeply, but I don't think bug in webpack-dev-server, I think it is bug with webpack here

alexander-akait avatar Mar 25 '21 16:03 alexander-akait

Give me time to look at this deeply, but I don't think bug in webpack-dev-server, I think it is bug with webpack here

@alexander-akait No problem. All I know is it worked fine with the Webpack 4 stack, so it's a regression one way or another.

slightlyfaulty avatar Mar 25 '21 16:03 slightlyfaulty

@slightlyfaulty Maybe it is limitation, I want to get answer from @sokra, in this case we should share ./node_modules/dev-server/client/default/index.js and ./node_modules/webpack/hot/dev-server.js and runtime code between entry points, i.e. create shared/runtime chunk(s), but without optimization.runtimeChunk, webpack doesn't do it, If we initially knew how you would use them (for example from index.html) we will apply runtimeChunk optimization by default.

https://webpack.js.org/configuration/optimization/#optimizationruntimechunk

We have warning about it:

Warning Imported modules are initialized for each runtime chunk separately, so if you include multiple entry points on a page, beware of this behavior. You will probably want to set it to single or use another configuration that allows you to only have one runtime instance.

alexander-akait avatar Mar 25 '21 16:03 alexander-akait

Other idea - output the warning in runtime and provide example how to fix it for better DX

alexander-akait avatar Mar 25 '21 16:03 alexander-akait

Running multiple entries on a single page that do not share a runtime chunk (e. g. with runtimeChunk: single) from the same compilation are not supported. Please use a shared runtime chunk. There are weird side effects when doing this. Seems like HMR not working is one of them.

sokra avatar Mar 26 '21 15:03 sokra

@sokra If it's not possible in Webpack 5 then fair enough. I think there are just a lot of people, like myself, who were doing this in Webpack 4 and it worked perfectly out the box.

Perhaps this limitation of Webpack 5 should be added to the migration guide if it isn't already.

slightlyfaulty avatar Mar 26 '21 16:03 slightlyfaulty