Skip to content

Commit 96e1634

Browse files
committed
feat: utilise EntryPlugin for proper entry injection in Webpack 5
1 parent 54bd9b1 commit 96e1634

File tree

1 file changed

+43
-8
lines changed

1 file changed

+43
-8
lines changed

lib/index.js

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
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');
39
const ConstDependency = require('webpack/lib/dependencies/ConstDependency');
410
const { refreshGlobal, webpackRequire, webpackVersion } = require('./globals');
511
const {
@@ -72,11 +78,40 @@ class ReactRefreshPlugin {
7278
const logger = compiler.getInfrastructureLogger(this.constructor.name);
7379
let loggedHotWarning = false;
7480

75-
// Inject react-refresh context to all Webpack entry points
76-
compiler.options.entry = injectRefreshEntry(
77-
compiler.options.entry,
78-
getAdditionalEntries({ options: this.options, devServer: compiler.options.devServer })
79-
);
81+
// Inject react-refresh context to all Webpack entry points.
82+
// This should create `EntryDependency` objects when available,
83+
// and fallback to patching the `entry` object for legacy workflows.
84+
const additionalEntries = getAdditionalEntries({
85+
devServer: compiler.options.devServer,
86+
options: this.options,
87+
});
88+
if (!EntryPlugin) {
89+
compiler.options.entry = injectRefreshEntry(compiler.options.entry, additionalEntries);
90+
} else {
91+
compiler.hooks.make.tapAsync(
92+
// `Number.NEGATIVE_INFINITY` ensures this will run before any other entries
93+
{ name: this.constructor.name, stage: Number.NEGATIVE_INFINITY },
94+
(compilation, callback) => {
95+
additionalEntries.prependEntries.forEach((entry) => {
96+
/** @type {import('webpack').EntryOptions} */
97+
const entryOptions = { name: undefined };
98+
const dependency = EntryPlugin.createDependency(entry, entryOptions);
99+
compilation.addEntry(compilation.context, dependency, entryOptions, (err) => {
100+
callback(err);
101+
});
102+
});
103+
104+
additionalEntries.overlayEntries.forEach((entry) => {
105+
/** @type {import('webpack').EntryOptions} */
106+
const entryOptions = { dependOn: injectRefreshEntry.socketEntries, name: undefined };
107+
const dependency = EntryPlugin.createDependency(entry, entryOptions);
108+
compilation.addEntry(compilation.context, dependency, entryOptions, (err) => {
109+
callback(err);
110+
});
111+
});
112+
}
113+
);
114+
}
80115

81116
// Inject necessary modules to bundle's global scope
82117
/** @type {Record<string, string | boolean>}*/
@@ -217,8 +252,8 @@ class ReactRefreshPlugin {
217252
);
218253

219254
compilation.hooks.normalModuleLoader.tap(
220-
// `Infinity` ensures this check will run only after all other taps
221-
{ name: this.constructor.name, stage: Infinity },
255+
// `Number.POSITIVE_INFINITY` ensures this check will run only after all other taps
256+
{ name: this.constructor.name, stage: Number.POSITIVE_INFINITY },
222257
// Check for existence of the HMR runtime -
223258
// it is the foundation to this plugin working correctly
224259
(context) => {

0 commit comments

Comments
 (0)