Skip to content

Commit f0a3147

Browse files
author
i
committed
feat: add backwards compatible option reactRefreshPrefix
1 parent 06c4d55 commit f0a3147

File tree

3 files changed

+42
-11
lines changed

3 files changed

+42
-11
lines changed

packages/plugin-react/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
## Unreleased
44

5+
### Add backwards compatible option `reactRefreshPrefix`
6+
7+
Add backwards compatible option `reactRefreshPrefix` to set React refresh runtime url prefix.
8+
This is useful in module federation context to enable HMR by setting the host url on a vite config which is serving a remote app.
9+
See full discussion here: https://github.com/module-federation/vite/issues/183#issuecomment-2751825367
10+
11+
```ts
12+
export default defineConfig(({ command }) => {
13+
return {
14+
plugins: [react({ reactRefreshPrefix: 'http://localhost:3000' })],
15+
}
16+
})
17+
```
18+
519
## 4.3.4 (2024-11-26)
620

721
### Add Vite 6 to peerDependencies range

packages/plugin-react/src/fast-refresh.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import fs from 'node:fs'
22
import path from 'node:path'
33
import { createRequire } from 'node:module'
4+
import { type Options } from './index'
45

5-
export const runtimePublicPath = '/@react-refresh'
6+
export const runtimePublicPath = (
7+
reactRefreshPrefix?: Options['reactRefreshPrefix'],
8+
): string => `${reactRefreshPrefix ?? ''}/@react-refresh`
69

710
const _require = createRequire(import.meta.url)
811
const reactRefreshDir = path.dirname(
@@ -21,15 +24,16 @@ export default exports
2124
`
2225

2326
export const preambleCode = `
24-
import RefreshRuntime from "__BASE__${runtimePublicPath.slice(1)}"
27+
import RefreshRuntime from "__BASE__${runtimePublicPath().slice(1)}"
2528
RefreshRuntime.injectIntoGlobalHook(window)
2629
window.$RefreshReg$ = () => {}
2730
window.$RefreshSig$ = () => (type) => type
2831
window.__vite_plugin_react_preamble_installed__ = true
2932
`
3033

31-
const sharedHeader = `
32-
import RefreshRuntime from "${runtimePublicPath}";
34+
const sharedHeader = (opts: Options) =>
35+
`
36+
import RefreshRuntime from "${runtimePublicPath(opts.reactRefreshPrefix)}";
3337
3438
const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
3539
`.replace(/\n+/g, '')
@@ -74,9 +78,13 @@ if (import.meta.hot && !inWebWorker) {
7478
});
7579
}`
7680

77-
export function addRefreshWrapper(code: string, id: string): string {
81+
export function addRefreshWrapper(
82+
code: string,
83+
id: string,
84+
opts: Options,
85+
): string {
7886
return (
79-
sharedHeader +
87+
sharedHeader(opts) +
8088
functionHeader.replace('__SOURCE__', JSON.stringify(id)) +
8189
code +
8290
functionFooter +
@@ -87,6 +95,7 @@ export function addRefreshWrapper(code: string, id: string): string {
8795
export function addClassComponentRefreshWrapper(
8896
code: string,
8997
id: string,
98+
opts: Options,
9099
): string {
91-
return sharedHeader + code + sharedFooter(id)
100+
return sharedHeader(opts) + code + sharedFooter(id)
92101
}

packages/plugin-react/src/index.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ export interface Options {
4747
babel?:
4848
| BabelOptions
4949
| ((id: string, options: { ssr?: boolean }) => BabelOptions)
50+
/**
51+
* React refresh runtime url prefix.
52+
* Useful in module federation context to enable HMR by
53+
* setting the host url on a vite config which is serving a remote app.
54+
* @example
55+
* reactRefreshPrefix: 'http://localhost:3000'
56+
*/
57+
reactRefreshPrefix?: string
5058
}
5159

5260
export type BabelOptions = Omit<
@@ -261,9 +269,9 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
261269
let code = result.code!
262270
if (useFastRefresh) {
263271
if (refreshContentRE.test(code)) {
264-
code = addRefreshWrapper(code, id)
272+
code = addRefreshWrapper(code, id, opts)
265273
} else if (reactCompRE.test(code)) {
266-
code = addClassComponentRefreshWrapper(code, id)
274+
code = addClassComponentRefreshWrapper(code, id, opts)
267275
}
268276
}
269277
return { code, map: result.map }
@@ -299,12 +307,12 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
299307
},
300308
}),
301309
resolveId(id) {
302-
if (id === runtimePublicPath) {
310+
if (id === runtimePublicPath(opts.reactRefreshPrefix)) {
303311
return id
304312
}
305313
},
306314
load(id) {
307-
if (id === runtimePublicPath) {
315+
if (id === runtimePublicPath(opts.reactRefreshPrefix)) {
308316
return runtimeCode
309317
}
310318
},

0 commit comments

Comments
 (0)