@@ -3,6 +3,7 @@ const { getRefreshGlobalScope } = require('./globals');
33const {
44 getAdditionalEntries,
55 getIntegrationEntry,
6+ getLibraryNamespace,
67 getSocketIntegration,
78 injectRefreshLoader,
89 makeRefreshRuntimeModule,
@@ -15,7 +16,7 @@ class ReactRefreshPlugin {
1516 * @param {import('./types').ReactRefreshPluginOptions } [options] Options for react-refresh-plugin.
1617 */
1718 constructor ( options = { } ) {
18- validateOptions ( schema , options , {
19+ validateOptions ( /** @type { Parameters<typeof validateOptions>[0] } */ ( schema ) , options , {
1920 name : 'React Refresh Plugin' ,
2021 baseDataPath : 'options' ,
2122 } ) ;
@@ -53,13 +54,13 @@ class ReactRefreshPlugin {
5354 const webpack = compiler . webpack || require ( 'webpack' ) ;
5455 const {
5556 DefinePlugin,
56- EntryDependency,
5757 EntryPlugin,
5858 ModuleFilenameHelpers,
5959 NormalModule,
6060 ProvidePlugin,
6161 RuntimeGlobals,
6262 Template,
63+ dependencies : { ModuleDependency } ,
6364 } = webpack ;
6465
6566 // Inject react-refresh context to all Webpack entry points.
@@ -70,23 +71,33 @@ class ReactRefreshPlugin {
7071 new EntryPlugin ( compiler . context , entry , { name : undefined } ) . apply ( compiler ) ;
7172 }
7273
73- const integrationEntry = getIntegrationEntry ( this . options . overlay . sockIntegration ) ;
74+ /** @type { { name?: string; index?: number }[] } */
7475 const socketEntryData = [ ] ;
75- compiler . hooks . make . tap (
76- { name : this . constructor . name , stage : Number . POSITIVE_INFINITY } ,
77- ( compilation ) => {
78- // Exhaustively search all entries for `integrationEntry`.
79- // If found, mark those entries and the index of `integrationEntry`.
80- for ( const [ name , entryData ] of compilation . entries . entries ( ) ) {
81- const index = entryData . dependencies . findIndex (
82- ( dep ) => dep . request && dep . request . includes ( integrationEntry )
83- ) ;
84- if ( index !== - 1 ) {
85- socketEntryData . push ( { name, index } ) ;
76+
77+ /** @type {string | undefined } */
78+ let integrationEntry ;
79+ if ( this . options . overlay && this . options . overlay . sockIntegration ) {
80+ integrationEntry = getIntegrationEntry ( this . options . overlay . sockIntegration ) ;
81+ }
82+
83+ if ( integrationEntry ) {
84+ compiler . hooks . make . tap (
85+ { name : this . constructor . name , stage : Number . POSITIVE_INFINITY } ,
86+ ( compilation ) => {
87+ // Exhaustively search all entries for `integrationEntry`.
88+ // If found, mark those entries and the index of `integrationEntry`.
89+ for ( const [ name , entryData ] of compilation . entries . entries ( ) ) {
90+ const index = entryData . dependencies . findIndex ( ( dep ) => {
91+ if ( ! ( dep instanceof ModuleDependency ) ) return false ;
92+ return dep . request . includes ( integrationEntry ) ;
93+ } ) ;
94+ if ( index !== - 1 ) {
95+ socketEntryData . push ( { name, index } ) ;
96+ }
8697 }
8798 }
88- }
89- ) ;
99+ ) ;
100+ }
90101
91102 // Overlay entries need to be injected AFTER integration's entry,
92103 // so we will loop through everything in `finishMake` instead of `make`.
@@ -97,37 +108,39 @@ class ReactRefreshPlugin {
97108 name : this . constructor . name ,
98109 stage : Number . MIN_SAFE_INTEGER + ( overlayEntries . length - idx - 1 ) ,
99110 } ,
100- ( compilation ) => {
111+ async ( compilation ) => {
101112 // Only hook into the current compiler
102- if ( compilation . compiler !== compiler ) {
103- return Promise . resolve ( ) ;
104- }
113+ if ( compilation . compiler !== compiler ) return ;
105114
106115 const injectData = socketEntryData . length ? socketEntryData : [ { name : undefined } ] ;
107- return Promise . all (
116+ await Promise . all (
108117 injectData . map ( ( { name, index } ) => {
109- return new Promise ( ( resolve , reject ) => {
110- const options = { name } ;
111- const dep = EntryPlugin . createDependency ( entry , options ) ;
112- compilation . addEntry ( compiler . context , dep , options , ( err ) => {
113- if ( err ) return reject ( err ) ;
114-
115- // If the entry is not a global one,
116- // and we have registered the index for integration entry,
117- // we will reorder all entry dependencies to our desired order.
118- // That is, to have additional entries DIRECTLY behind integration entry.
119- if ( name && typeof index !== 'undefined' ) {
120- const entryData = compilation . entries . get ( name ) ;
121- entryData . dependencies . splice (
122- index + 1 ,
123- 0 ,
124- entryData . dependencies . splice ( entryData . dependencies . length - 1 , 1 ) [ 0 ]
125- ) ;
126- }
127-
128- resolve ( ) ;
129- } ) ;
130- } ) ;
118+ return /** @type {Promise<void> } */ (
119+ new Promise ( ( resolve , reject ) => {
120+ const options = { name } ;
121+ const dep = EntryPlugin . createDependency ( entry , options ) ;
122+ compilation . addEntry ( compiler . context , dep , options , ( err ) => {
123+ if ( err ) return reject ( err ) ;
124+
125+ // If the entry is not a global one,
126+ // and we have registered the index for integration entry,
127+ // we will reorder all entry dependencies to our desired order.
128+ // That is, to have additional entries DIRECTLY behind integration entry.
129+ if ( name && typeof index !== 'undefined' ) {
130+ const entryData = compilation . entries . get ( name ) ;
131+ if ( entryData ) {
132+ entryData . dependencies . splice (
133+ index + 1 ,
134+ 0 ,
135+ entryData . dependencies . splice ( entryData . dependencies . length - 1 , 1 ) [ 0 ]
136+ ) ;
137+ }
138+ }
139+
140+ resolve ( ) ;
141+ } ) ;
142+ } )
143+ ) ;
131144 } )
132145 ) ;
133146 }
@@ -143,21 +156,20 @@ class ReactRefreshPlugin {
143156 $RefreshSig$ : `${ refreshGlobal } .signature` ,
144157 'typeof $RefreshReg$' : 'function' ,
145158 'typeof $RefreshSig$' : 'function' ,
146-
147- // Library mode
148- __react_refresh_library__ : JSON . stringify (
149- Template . toIdentifier (
150- this . options . library ||
151- compiler . options . output . uniqueName ||
152- compiler . options . output . library
153- )
154- ) ,
155159 } ;
156160 /** @type {Record<string, string> } */
157161 const providedModules = {
158162 __react_refresh_utils__ : require . resolve ( './runtime/RefreshUtils' ) ,
159163 } ;
160164
165+ // Library mode
166+ const libraryNamespace = getLibraryNamespace ( this . options , compiler . options . output ) ;
167+ if ( libraryNamespace ) {
168+ definedModules [ '__react_refresh_library__' ] = JSON . stringify (
169+ Template . toIdentifier ( libraryNamespace )
170+ ) ;
171+ }
172+
161173 if ( this . options . overlay === false ) {
162174 // Stub errorOverlay module so their calls can be erased
163175 definedModules . __react_refresh_error_overlay__ = false ;
@@ -178,7 +190,15 @@ class ReactRefreshPlugin {
178190 new DefinePlugin ( definedModules ) . apply ( compiler ) ;
179191 new ProvidePlugin ( providedModules ) . apply ( compiler ) ;
180192
181- const match = ModuleFilenameHelpers . matchObject . bind ( undefined , this . options ) ;
193+ /**
194+ * @param {string } [str]
195+ * @returns boolean
196+ */
197+ const match = ( str ) => {
198+ if ( str == null ) return false ;
199+ return ModuleFilenameHelpers . matchObject ( this . options , str ) ;
200+ } ;
201+
182202 let loggedHotWarning = false ;
183203 compiler . hooks . compilation . tap (
184204 this . constructor . name ,
@@ -188,9 +208,6 @@ class ReactRefreshPlugin {
188208 return ;
189209 }
190210
191- // Set factory for EntryDependency which is used to initialise the module
192- compilation . dependencyFactories . set ( EntryDependency , normalModuleFactory ) ;
193-
194211 const ReactRefreshRuntimeModule = makeRefreshRuntimeModule ( webpack ) ;
195212 compilation . hooks . additionalTreeRuntimeRequirements . tap (
196213 this . constructor . name ,
0 commit comments