Skip to content

Commit 57895c9

Browse files
committed
feat: utilise EntryPlugin for proper entry injection in Webpack 5
1 parent 2efdc86 commit 57895c9

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 {
@@ -80,11 +86,40 @@ class ReactRefreshPlugin {
8086
return;
8187
}
8288

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+
}
88123

89124
// Inject necessary modules to bundle's global scope
90125
/** @type {Record<string, string | boolean>}*/
@@ -222,8 +257,8 @@ class ReactRefreshPlugin {
222257
);
223258

224259
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 },
227262
// Check for existence of the HMR runtime -
228263
// it is the foundation to this plugin working correctly
229264
(context) => {

0 commit comments

Comments
 (0)