From db9d3f4f975f40d39a6722c3deb600a13a77f261 Mon Sep 17 00:00:00 2001 From: protoEvangelion Date: Tue, 8 Apr 2025 12:50:46 -0500 Subject: [PATCH 1/7] feat: add reactRefreshHost option to support module federation HMR --- packages/common/refresh-utils.ts | 4 +++- packages/plugin-react-swc/CHANGELOG.md | 12 ++++++++++++ packages/plugin-react-swc/README.md | 10 ++++++++++ packages/plugin-react-swc/src/index.ts | 10 ++++++++++ packages/plugin-react/CHANGELOG.md | 12 ++++++++++++ packages/plugin-react/README.md | 10 ++++++++++ packages/plugin-react/src/index.ts | 9 +++++++++ 7 files changed, 66 insertions(+), 1 deletion(-) diff --git a/packages/common/refresh-utils.ts b/packages/common/refresh-utils.ts index 00882879..4663696e 100644 --- a/packages/common/refresh-utils.ts +++ b/packages/common/refresh-utils.ts @@ -21,6 +21,7 @@ export function addRefreshWrapper( map: M | string | typeof avoidSourceMapOption, pluginName: string, id: string, + reactRefreshHost = '', ): { code: string; map: M | null | string } { const hasRefresh = refreshContentRE.test(code) const onlyReactComp = !hasRefresh && reactCompRE.test(code) @@ -70,7 +71,8 @@ if (import.meta.hot && !inWebWorker) { } const sharedHead = removeLineBreaksIfNeeded( - `import * as RefreshRuntime from "${runtimePublicPath}"; + `import * as RefreshRuntime from "${reactRefreshHost}${runtimePublicPath}"; + const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope; `, diff --git a/packages/plugin-react-swc/CHANGELOG.md b/packages/plugin-react-swc/CHANGELOG.md index 08c8c3da..d85a4fa0 100644 --- a/packages/plugin-react-swc/CHANGELOG.md +++ b/packages/plugin-react-swc/CHANGELOG.md @@ -2,6 +2,18 @@ ## Unreleased +### Add option `reactRefreshHost` + +Add option `reactRefreshHost` to set React refresh runtime url prefix. +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. +See full discussion here: https://github.com/module-federation/vite/issues/183#issuecomment-2751825367 + +```ts +export default defineConfig({ + plugins: [react({ reactRefreshHost: 'http://localhost:3000' })], +}) +``` + ## 3.9.0-beta.2 (2025-04-09) ## 3.9.0-beta.0 (2025-04-09) diff --git a/packages/plugin-react-swc/README.md b/packages/plugin-react-swc/README.md index b00ac0be..311d7413 100644 --- a/packages/plugin-react-swc/README.md +++ b/packages/plugin-react-swc/README.md @@ -93,6 +93,16 @@ react({ }) ``` +### reactRefreshHost + +The `reactRefreshHost` option is only necessary in a module federation context. It allows HMR to work between a remote & host server. In your remote vite config you would add your host origin: + +```js +react({ reactRefreshHost: 'http://localhost:3000' }) +``` + +Under the hood this simply updates the react refresh url from "/@react-refresh" to "http://localhost:3000/@react-refresh" to ensure you get only one Fast Refresh runtime in the whole application. + ### useAtYourOwnRisk_mutateSwcOptions The future of Vite is with OXC, and from the beginning this was a design choice to not exposed too many specialties from SWC so that Vite React users can move to another transformer later. diff --git a/packages/plugin-react-swc/src/index.ts b/packages/plugin-react-swc/src/index.ts index 52f211f4..44ebffbd 100644 --- a/packages/plugin-react-swc/src/index.ts +++ b/packages/plugin-react-swc/src/index.ts @@ -58,6 +58,14 @@ type Options = { * Exclusion of node_modules should be handled by the function if needed. */ parserConfig?: (id: string) => ParserConfig | undefined + /** + * React refresh runtime url prefix. + * Useful in module federation context to enable HMR by + * setting the host url on a vite config which is serving a remote app. + * @example + * reactRefreshHost: 'http://localhost:3000' + */ + reactRefreshHost?: string /** * The future of Vite is with OXC, and from the beginning this was a design choice * to not exposed too many specialties from SWC so that Vite React users can move to @@ -78,6 +86,7 @@ const react = (_options?: Options): PluginOption[] => { : undefined, devTarget: _options?.devTarget ?? 'es2020', parserConfig: _options?.parserConfig, + reactRefreshHost: _options?.reactRefreshHost, useAtYourOwnRisk_mutateSwcOptions: _options?.useAtYourOwnRisk_mutateSwcOptions, } @@ -152,6 +161,7 @@ const react = (_options?: Options): PluginOption[] => { result.map!, '@vitejs/plugin-react-swc', id, + options.reactRefreshHost, ) }, }, diff --git a/packages/plugin-react/CHANGELOG.md b/packages/plugin-react/CHANGELOG.md index 928a751c..361c698d 100644 --- a/packages/plugin-react/CHANGELOG.md +++ b/packages/plugin-react/CHANGELOG.md @@ -2,6 +2,18 @@ ## Unreleased +### Add option `reactRefreshHost` + +Add option `reactRefreshHost` to set React refresh runtime url prefix. +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. +See full discussion here: https://github.com/module-federation/vite/issues/183#issuecomment-2751825367 + +```ts +export default defineConfig({ + plugins: [react({ reactRefreshHost: 'http://localhost:3000' })], +}) +``` + ## 4.4.0-beta.1 (2025-04-09) ## 4.4.0-beta.0 (2025-04-09) diff --git a/packages/plugin-react/README.md b/packages/plugin-react/README.md index 27683dd4..e8883df7 100644 --- a/packages/plugin-react/README.md +++ b/packages/plugin-react/README.md @@ -94,6 +94,16 @@ This option does not enable _code transformation_. That is handled by esbuild. Here's the [complete list of Babel parser plugins](https://babeljs.io/docs/en/babel-parser#ecmascript-proposalshttpsgithubcombabelproposals). +### reactRefreshHost + +The `reactRefreshHost` option is only necessary in a module federation context. It allows HMR to work between a remote & host server. In your remote vite config you would add your host origin: + +```js +react({ reactRefreshHost: 'http://localhost:3000' }) +``` + +Under the hood this simply updates the react refresh url from "/@react-refresh" to "http://localhost:3000/@react-refresh" to ensure you get only one Fast Refresh runtime in the whole application. + ## Middleware mode In [middleware mode](https://vite.dev/config/server-options.html#server-middlewaremode), you should make sure your entry `index.html` file is transformed by Vite. Here's an example for an Express server: diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index 26739e56..d2034421 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -49,6 +49,14 @@ export interface Options { babel?: | BabelOptions | ((id: string, options: { ssr?: boolean }) => BabelOptions) + /** + * React refresh runtime url prefix. + * Useful in module federation context to enable HMR by + * setting the host url on a vite config which is serving a remote app. + * @example + * reactRefreshHost: 'http://localhost:3000' + */ + reactRefreshHost?: string } export type BabelOptions = Omit< @@ -263,6 +271,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] { result.map!, '@vitejs/plugin-react', id, + opts.reactRefreshHost ) } }, From 7ea3fa794d89828d8a486173eda68a904fb075b8 Mon Sep 17 00:00:00 2001 From: protoEvangelion Date: Wed, 9 Apr 2025 21:24:04 -0500 Subject: [PATCH 2/7] feat: prettier fix --- packages/plugin-react/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index d2034421..98ec8c6b 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -271,7 +271,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] { result.map!, '@vitejs/plugin-react', id, - opts.reactRefreshHost + opts.reactRefreshHost, ) } }, From 5e9fe92b34bb302cacfa591c8223cfa07abdebb7 Mon Sep 17 00:00:00 2001 From: protoEvangelion Date: Thu, 10 Apr 2025 08:00:55 -0500 Subject: [PATCH 3/7] feat: add usage of base to docs --- packages/plugin-react-swc/README.md | 2 +- packages/plugin-react/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin-react-swc/README.md b/packages/plugin-react-swc/README.md index 311d7413..d4dae714 100644 --- a/packages/plugin-react-swc/README.md +++ b/packages/plugin-react-swc/README.md @@ -101,7 +101,7 @@ The `reactRefreshHost` option is only necessary in a module federation context. react({ reactRefreshHost: 'http://localhost:3000' }) ``` -Under the hood this simply updates the react refresh url from "/@react-refresh" to "http://localhost:3000/@react-refresh" to ensure you get only one Fast Refresh runtime in the whole application. +Under the hood this simply updates the react refresh url from "/@react-refresh" to "http://localhost:3000/@react-refresh" to ensure you get only one Fast Refresh runtime in the whole application. Note that if you define `base` you need to include that in the url provided like: `http://localhost:3000/{base}`. ### useAtYourOwnRisk_mutateSwcOptions diff --git a/packages/plugin-react/README.md b/packages/plugin-react/README.md index e8883df7..1107f8f6 100644 --- a/packages/plugin-react/README.md +++ b/packages/plugin-react/README.md @@ -102,7 +102,7 @@ The `reactRefreshHost` option is only necessary in a module federation context. react({ reactRefreshHost: 'http://localhost:3000' }) ``` -Under the hood this simply updates the react refresh url from "/@react-refresh" to "http://localhost:3000/@react-refresh" to ensure you get only one Fast Refresh runtime in the whole application. +Under the hood this simply updates the react refresh url from "/@react-refresh" to "http://localhost:3000/@react-refresh" to ensure you get only one Fast Refresh runtime in the whole application. Note that if you define `base` you need to include that in the url provided like: `http://localhost:3000/{base}`. ## Middleware mode From 29511e193f36ef8e79a3b2c05ffe1afeda01bc0a Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 11 Apr 2025 10:44:14 +0900 Subject: [PATCH 4/7] docs: tweak sentence slightly --- packages/plugin-react-swc/README.md | 4 ++-- packages/plugin-react/README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/plugin-react-swc/README.md b/packages/plugin-react-swc/README.md index d4dae714..9a4af3b5 100644 --- a/packages/plugin-react-swc/README.md +++ b/packages/plugin-react-swc/README.md @@ -95,13 +95,13 @@ react({ ### reactRefreshHost -The `reactRefreshHost` option is only necessary in a module federation context. It allows HMR to work between a remote & host server. In your remote vite config you would add your host origin: +The `reactRefreshHost` option is only necessary in a module federation context. It enables HMR to work between a remote & host application. In your remote vite config, you would add your host origin: ```js react({ reactRefreshHost: 'http://localhost:3000' }) ``` -Under the hood this simply updates the react refresh url from "/@react-refresh" to "http://localhost:3000/@react-refresh" to ensure you get only one Fast Refresh runtime in the whole application. Note that if you define `base` you need to include that in the url provided like: `http://localhost:3000/{base}`. +Under the hood, this simply updates the React Fash Refresh runtime URL from `/@react-refresh` to `http://localhost:3000/@react-refresh` to ensure there is only one Refresh runtime across the whole application. Note that if you define `base` option in the host application, you need to include it in the option, like: `http://localhost:3000/{base}`. ### useAtYourOwnRisk_mutateSwcOptions diff --git a/packages/plugin-react/README.md b/packages/plugin-react/README.md index 1107f8f6..b63f7897 100644 --- a/packages/plugin-react/README.md +++ b/packages/plugin-react/README.md @@ -96,13 +96,13 @@ Here's the [complete list of Babel parser plugins](https://babeljs.io/docs/en/ba ### reactRefreshHost -The `reactRefreshHost` option is only necessary in a module federation context. It allows HMR to work between a remote & host server. In your remote vite config you would add your host origin: +The `reactRefreshHost` option is only necessary in a module federation context. It enables HMR to work between a remote & host application. In your remote vite config, you would add your host origin: ```js react({ reactRefreshHost: 'http://localhost:3000' }) ``` -Under the hood this simply updates the react refresh url from "/@react-refresh" to "http://localhost:3000/@react-refresh" to ensure you get only one Fast Refresh runtime in the whole application. Note that if you define `base` you need to include that in the url provided like: `http://localhost:3000/{base}`. +Under the hood, this simply updates the React Fash Refresh runtime URL from `/@react-refresh` to `http://localhost:3000/@react-refresh` to ensure there is only one Refresh runtime across the whole application. Note that if you define `base` option in the host application, you need to include it in the option, like: `http://localhost:3000/{base}`. ## Middleware mode From 1fd359965db08d372b43e5789f90ae479e2736ab Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 11 Apr 2025 10:49:55 +0900 Subject: [PATCH 5/7] docs: tweak changelog slightly --- packages/plugin-react-swc/CHANGELOG.md | 6 +++--- packages/plugin-react/CHANGELOG.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/plugin-react-swc/CHANGELOG.md b/packages/plugin-react-swc/CHANGELOG.md index d85a4fa0..4a00eb52 100644 --- a/packages/plugin-react-swc/CHANGELOG.md +++ b/packages/plugin-react-swc/CHANGELOG.md @@ -2,10 +2,10 @@ ## Unreleased -### Add option `reactRefreshHost` +### Add `reactRefreshHost` option -Add option `reactRefreshHost` to set React refresh runtime url prefix. -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. +Add `reactRefreshHost` option to set a React Fast Refresh runtime URL prefix. +This is useful in a module federation context to enable HMR by specifying the host application URL in the vite config of a remote application. See full discussion here: https://github.com/module-federation/vite/issues/183#issuecomment-2751825367 ```ts diff --git a/packages/plugin-react/CHANGELOG.md b/packages/plugin-react/CHANGELOG.md index 361c698d..39943aa7 100644 --- a/packages/plugin-react/CHANGELOG.md +++ b/packages/plugin-react/CHANGELOG.md @@ -2,10 +2,10 @@ ## Unreleased -### Add option `reactRefreshHost` +### Add `reactRefreshHost` option -Add option `reactRefreshHost` to set React refresh runtime url prefix. -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. +Add `reactRefreshHost` option to set a React Fast Refresh runtime URL prefix. +This is useful in a module federation context to enable HMR by specifying the host application URL in the vite config of a remote application. See full discussion here: https://github.com/module-federation/vite/issues/183#issuecomment-2751825367 ```ts From 68e88e1e650398b5bf90c34c8caa5eb721f833da Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 11 Apr 2025 10:51:15 +0900 Subject: [PATCH 6/7] fix: incorrect sourcemap offset --- packages/common/refresh-utils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/common/refresh-utils.ts b/packages/common/refresh-utils.ts index 4663696e..559cbaa0 100644 --- a/packages/common/refresh-utils.ts +++ b/packages/common/refresh-utils.ts @@ -72,7 +72,6 @@ if (import.meta.hot && !inWebWorker) { const sharedHead = removeLineBreaksIfNeeded( `import * as RefreshRuntime from "${reactRefreshHost}${runtimePublicPath}"; - const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope; `, From ef998b7582588fd911159b7602e49c34873dca3e Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 11 Apr 2025 10:54:09 +0900 Subject: [PATCH 7/7] docs: align jsdoc with readme --- packages/plugin-react-swc/CHANGELOG.md | 2 +- packages/plugin-react-swc/README.md | 2 +- packages/plugin-react-swc/src/index.ts | 6 +++--- packages/plugin-react/CHANGELOG.md | 2 +- packages/plugin-react/README.md | 2 +- packages/plugin-react/src/index.ts | 6 +++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/plugin-react-swc/CHANGELOG.md b/packages/plugin-react-swc/CHANGELOG.md index 4a00eb52..e58b5f9f 100644 --- a/packages/plugin-react-swc/CHANGELOG.md +++ b/packages/plugin-react-swc/CHANGELOG.md @@ -5,7 +5,7 @@ ### Add `reactRefreshHost` option Add `reactRefreshHost` option to set a React Fast Refresh runtime URL prefix. -This is useful in a module federation context to enable HMR by specifying the host application URL in the vite config of a remote application. +This is useful in a module federation context to enable HMR by specifying the host application URL in the Vite config of a remote application. See full discussion here: https://github.com/module-federation/vite/issues/183#issuecomment-2751825367 ```ts diff --git a/packages/plugin-react-swc/README.md b/packages/plugin-react-swc/README.md index 9a4af3b5..76bd52e6 100644 --- a/packages/plugin-react-swc/README.md +++ b/packages/plugin-react-swc/README.md @@ -95,7 +95,7 @@ react({ ### reactRefreshHost -The `reactRefreshHost` option is only necessary in a module federation context. It enables HMR to work between a remote & host application. In your remote vite config, you would add your host origin: +The `reactRefreshHost` option is only necessary in a module federation context. It enables HMR to work between a remote & host application. In your remote Vite config, you would add your host origin: ```js react({ reactRefreshHost: 'http://localhost:3000' }) diff --git a/packages/plugin-react-swc/src/index.ts b/packages/plugin-react-swc/src/index.ts index 44ebffbd..9c33c224 100644 --- a/packages/plugin-react-swc/src/index.ts +++ b/packages/plugin-react-swc/src/index.ts @@ -59,9 +59,9 @@ type Options = { */ parserConfig?: (id: string) => ParserConfig | undefined /** - * React refresh runtime url prefix. - * Useful in module federation context to enable HMR by - * setting the host url on a vite config which is serving a remote app. + * React Fast Refresh runtime URL prefix. + * Useful in a module federation context to enable HMR by specifying + * the host application URL in a Vite config of a remote application. * @example * reactRefreshHost: 'http://localhost:3000' */ diff --git a/packages/plugin-react/CHANGELOG.md b/packages/plugin-react/CHANGELOG.md index 39943aa7..90a1d8b7 100644 --- a/packages/plugin-react/CHANGELOG.md +++ b/packages/plugin-react/CHANGELOG.md @@ -5,7 +5,7 @@ ### Add `reactRefreshHost` option Add `reactRefreshHost` option to set a React Fast Refresh runtime URL prefix. -This is useful in a module federation context to enable HMR by specifying the host application URL in the vite config of a remote application. +This is useful in a module federation context to enable HMR by specifying the host application URL in the Vite config of a remote application. See full discussion here: https://github.com/module-federation/vite/issues/183#issuecomment-2751825367 ```ts diff --git a/packages/plugin-react/README.md b/packages/plugin-react/README.md index b63f7897..7eaa29ab 100644 --- a/packages/plugin-react/README.md +++ b/packages/plugin-react/README.md @@ -96,7 +96,7 @@ Here's the [complete list of Babel parser plugins](https://babeljs.io/docs/en/ba ### reactRefreshHost -The `reactRefreshHost` option is only necessary in a module federation context. It enables HMR to work between a remote & host application. In your remote vite config, you would add your host origin: +The `reactRefreshHost` option is only necessary in a module federation context. It enables HMR to work between a remote & host application. In your remote Vite config, you would add your host origin: ```js react({ reactRefreshHost: 'http://localhost:3000' }) diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index 98ec8c6b..0923207a 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -50,9 +50,9 @@ export interface Options { | BabelOptions | ((id: string, options: { ssr?: boolean }) => BabelOptions) /** - * React refresh runtime url prefix. - * Useful in module federation context to enable HMR by - * setting the host url on a vite config which is serving a remote app. + * React Fast Refresh runtime URL prefix. + * Useful in a module federation context to enable HMR by specifying + * the host application URL in the Vite config of a remote application. * @example * reactRefreshHost: 'http://localhost:3000' */