|
1 | 1 | const { validate: validateOptions } = require('schema-utils');
|
2 |
| -const { DefinePlugin, ModuleFilenameHelpers, ProvidePlugin, Template } = require('webpack'); |
| 2 | +const { |
| 3 | + DefinePlugin, |
| 4 | + EntryPlugin, |
| 5 | + ModuleFilenameHelpers, |
| 6 | + ProvidePlugin, |
| 7 | + Template, |
| 8 | +} = require('webpack'); |
3 | 9 | const ConstDependency = require('webpack/lib/dependencies/ConstDependency');
|
4 | 10 | const { refreshGlobal, webpackRequire, webpackVersion } = require('./globals');
|
5 | 11 | const {
|
@@ -80,11 +86,40 @@ class ReactRefreshPlugin {
|
80 | 86 | return;
|
81 | 87 | }
|
82 | 88 |
|
83 |
| - // Inject react-refresh context to all Webpack entry points |
84 |
| - compiler.options.entry = injectRefreshEntry( |
85 |
| - compiler.options.entry, |
86 |
| - getAdditionalEntries({ options: this.options, devServer: compiler.options.devServer }) |
87 |
| - ); |
| 89 | + // Inject react-refresh context to all Webpack entry points. |
| 90 | + // This should create `EntryDependency` objects when available, |
| 91 | + // and fallback to patching the `entry` object for legacy workflows. |
| 92 | + const additionalEntries = getAdditionalEntries({ |
| 93 | + devServer: compiler.options.devServer, |
| 94 | + options: this.options, |
| 95 | + }); |
| 96 | + if (!EntryPlugin) { |
| 97 | + compiler.options.entry = injectRefreshEntry(compiler.options.entry, additionalEntries); |
| 98 | + } else { |
| 99 | + compiler.hooks.make.tapAsync( |
| 100 | + // `Number.NEGATIVE_INFINITY` ensures this will run before any other entries |
| 101 | + { name: this.constructor.name, stage: Number.NEGATIVE_INFINITY }, |
| 102 | + (compilation, callback) => { |
| 103 | + additionalEntries.prependEntries.forEach((entry) => { |
| 104 | + /** @type {import('webpack').EntryOptions} */ |
| 105 | + const entryOptions = { name: undefined }; |
| 106 | + const dependency = EntryPlugin.createDependency(entry, entryOptions); |
| 107 | + compilation.addEntry(compilation.context, dependency, entryOptions, (err) => { |
| 108 | + callback(err); |
| 109 | + }); |
| 110 | + }); |
| 111 | + |
| 112 | + additionalEntries.overlayEntries.forEach((entry) => { |
| 113 | + /** @type {import('webpack').EntryOptions} */ |
| 114 | + const entryOptions = { dependOn: injectRefreshEntry.socketEntries, name: undefined }; |
| 115 | + const dependency = EntryPlugin.createDependency(entry, entryOptions); |
| 116 | + compilation.addEntry(compilation.context, dependency, entryOptions, (err) => { |
| 117 | + callback(err); |
| 118 | + }); |
| 119 | + }); |
| 120 | + } |
| 121 | + ); |
| 122 | + } |
88 | 123 |
|
89 | 124 | // Inject necessary modules to bundle's global scope
|
90 | 125 | /** @type {Record<string, string | boolean>}*/
|
@@ -222,8 +257,8 @@ class ReactRefreshPlugin {
|
222 | 257 | );
|
223 | 258 |
|
224 | 259 | compilation.hooks.normalModuleLoader.tap(
|
225 |
| - // `Infinity` ensures this check will run only after all other taps |
226 |
| - { name: this.constructor.name, stage: Infinity }, |
| 260 | + // `Number.POSITIVE_INFINITY` ensures this check will run only after all other taps |
| 261 | + { name: this.constructor.name, stage: Number.POSITIVE_INFINITY }, |
227 | 262 | // Check for existence of the HMR runtime -
|
228 | 263 | // it is the foundation to this plugin working correctly
|
229 | 264 | (context) => {
|
|
0 commit comments