@@ -202,8 +202,8 @@ class RolldownEnvironment extends DevEnvironment {
202
202
} ,
203
203
plugins : [
204
204
...plugins ,
205
- patchRuntimePlugin ( ) ,
206
- reactRefreshPlugin ( this . rolldownDevOptions ) ,
205
+ patchRuntimePlugin ( this . rolldownDevOptions ) ,
206
+ reactRefreshPlugin ( ) ,
207
207
] ,
208
208
}
209
209
this . instance = await rolldown . rolldown ( inputOptions )
@@ -257,7 +257,9 @@ class RolldownEnvironment extends DevEnvironment {
257
257
}
258
258
}
259
259
260
- function patchRuntimePlugin ( ) : rolldown . Plugin {
260
+ function patchRuntimePlugin (
261
+ rolldownDevOptions : RolldownDevOptions ,
262
+ ) : rolldown . Plugin {
261
263
return {
262
264
name : 'vite:rolldown-patch-runtime' ,
263
265
renderChunk ( code ) {
@@ -278,6 +280,9 @@ function patchRuntimePlugin(): rolldown.Plugin {
278
280
}
279
281
for (var i = 0; i < module.parents.length; i++) {` ,
280
282
)
283
+ if ( rolldownDevOptions . reactRefresh ) {
284
+ output . prepend ( getReactRefreshRuntimeCode ( ) )
285
+ }
281
286
return { code : output . toString ( ) , map : output . generateMap ( ) }
282
287
}
283
288
} ,
@@ -320,82 +325,64 @@ window.__rolldown_hot = hot;
320
325
return `(() => {/*** @vite/client ***/\n${ code } }\n)()`
321
326
}
322
327
323
- // TODO: workaround rolldownExperimental.reactPlugin which injects js to html via `load` hook
324
- // TODO: can we inject to "react" itself?
325
- function reactRefreshPlugin (
326
- rolldownDevOptions : RolldownDevOptions ,
327
- ) : rolldown . Plugin {
328
+ function reactRefreshPlugin ( ) : rolldown . Plugin {
328
329
return {
329
- name : 'react-hmr ' ,
330
+ name : 'vite:rolldown- react-refresh ' ,
330
331
transform : {
331
332
filter : {
332
333
code : {
333
334
include : [ '$RefreshReg$' ] ,
334
335
} ,
335
336
} ,
336
337
handler ( code , id ) {
337
- const output = new MagicString ( code )
338
- output . prepend ( `
339
- import * as __$refresh from 'virtual:react-refresh';
340
- const [$RefreshSig$, $RefreshReg$] = __$refresh.create(${ JSON . stringify ( id ) } );
341
- ` )
342
- output . append ( `
343
- __$refresh.setupHot(module.hot);
344
- ` )
345
- return { code : output . toString ( ) , map : output . generateMap ( ) }
346
- } ,
347
- } ,
348
- resolveId : {
349
- filter : {
350
- id : {
351
- include : [ / ^ v i r t u a l : r e a c t - r e f r e s h / ] ,
352
- } ,
353
- } ,
354
- handler : ( source ) => '\0' + source ,
355
- } ,
356
- load : {
357
- filter : {
358
- id : {
359
- include : [ / ^ \0 v i r t u a l : r e a c t - r e f r e s h / ] ,
360
- } ,
361
- } ,
362
- async handler ( id ) {
363
- if ( ! rolldownDevOptions . reactRefresh ) {
364
- return `export {}`
365
- }
366
- const resolved = require . resolve ( 'react-refresh/runtime' )
367
- if ( id === '\0virtual:react-refresh/entry' ) {
368
- return `
369
- import runtime from ${ JSON . stringify ( resolved ) } ;
370
- runtime.injectIntoGlobalHook(window);
371
- `
372
- }
373
- if ( id === '\0virtual:react-refresh' ) {
374
- return `
375
- import runtime from ${ JSON . stringify ( resolved ) } ;
376
-
377
- export const create = (file) => [
378
- runtime.createSignatureFunctionForTransform,
379
- (type, id) => runtime.register(type, file + '_' + id),
380
- ];
381
-
382
- function debounce(fn, delay) {
383
- let handle
384
- return () => {
385
- clearTimeout(handle)
386
- handle = setTimeout(fn, delay)
387
- }
388
- }
389
- const debouncedRefresh = debounce(runtime.performReactRefresh, 16);
390
-
391
- export function setupHot(hot) {
392
- hot.accept((prev) => {
393
- debouncedRefresh();
394
- });
395
- }
396
- `
397
- }
338
+ return [
339
+ `const [$RefreshSig$, $RefreshReg$] = __react_refresh_transform_define(${ JSON . stringify ( id ) } )` ,
340
+ code ,
341
+ `__react_refresh_transform_setupHot(module.hot)` ,
342
+ ] . join ( ';' )
398
343
} ,
399
344
} ,
400
345
}
401
346
}
347
+
348
+ // inject react refresh runtime in client runtime to ensure initialized early
349
+ function getReactRefreshRuntimeCode ( ) {
350
+ const code = fs . readFileSync (
351
+ path . resolve (
352
+ require . resolve ( 'react-refresh/runtime' ) ,
353
+ '..' ,
354
+ 'cjs/react-refresh-runtime.development.js' ,
355
+ ) ,
356
+ 'utf-8' ,
357
+ )
358
+ const output = new MagicString ( code )
359
+ output . prepend ( 'self.__react_refresh_runtime = {};\n' )
360
+ output . replaceAll ( 'process.env.NODE_ENV !== "production"' , 'true' )
361
+ output . replaceAll ( / \b e x p o r t s \. / g, '__react_refresh_runtime.' )
362
+ output . append ( `
363
+ (() => {
364
+ __react_refresh_runtime.injectIntoGlobalHook(self);
365
+
366
+ __react_refresh_transform_define = (file) => [
367
+ __react_refresh_runtime.createSignatureFunctionForTransform,
368
+ (type, id) => __react_refresh_runtime.register(type, file + '_' + id)
369
+ ];
370
+
371
+ __react_refresh_transform_setupHot = (hot) => {
372
+ hot.accept((prev) => {
373
+ debouncedRefresh();
374
+ });
375
+ };
376
+
377
+ function debounce(fn, delay) {
378
+ let handle
379
+ return () => {
380
+ clearTimeout(handle)
381
+ handle = setTimeout(fn, delay)
382
+ }
383
+ }
384
+ const debouncedRefresh = debounce(__react_refresh_runtime.performReactRefresh, 16);
385
+ })()
386
+ ` )
387
+ return output . toString ( )
388
+ }
0 commit comments