diff --git a/lib/utils/addEntries.js b/lib/utils/addEntries.js index fb5e542e75..117bd9a835 100644 --- a/lib/utils/addEntries.js +++ b/lib/utils/addEntries.js @@ -93,8 +93,9 @@ function addEntries(config, options, server) { config.plugins = config.plugins || []; if ( !config.plugins.find( - (plugin) => - plugin.constructor === webpack.HotModuleReplacementPlugin + // Check for the name rather than the constructor reference in case + // there are multiple copies of webpack installed + (plugin) => plugin.constructor.name === 'HotModuleReplacementPlugin' ) ) { config.plugins.push(new webpack.HotModuleReplacementPlugin()); diff --git a/test/server/utils/addEntries.test.js b/test/server/utils/addEntries.test.js index 608bd61a30..1bc6a6cef6 100644 --- a/test/server/utils/addEntries.test.js +++ b/test/server/utils/addEntries.test.js @@ -246,6 +246,26 @@ describe('addEntries util', () => { ]); }); + it("should not add the HMR plugin again if it's already there from a different webpack", () => { + const existingPlugin = new webpack.BannerPlugin('bruce'); + + // Simulate the inclusion of another webpack's HotModuleReplacementPlugin + class HotModuleReplacementPlugin {} + + const webpackOptions = Object.assign({}, config, { + plugins: [new HotModuleReplacementPlugin(), existingPlugin], + }); + const devServerOptions = { hot: true }; + + addEntries(webpackOptions, devServerOptions); + + expect(webpackOptions.plugins).toEqual([ + // Nothing should be injected + new HotModuleReplacementPlugin(), + existingPlugin, + ]); + }); + it('should can prevent duplicate entries from successive calls', () => { const webpackOptions = Object.assign({}, config); const devServerOptions = { hot: true };