Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/common/refresh-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function addRefreshWrapper<M extends { mappings: string }>(
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)
Expand Down Expand Up @@ -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;

`,
Expand Down
12 changes: 12 additions & 0 deletions packages/plugin-react-swc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions packages/plugin-react-swc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 10 additions & 0 deletions packages/plugin-react-swc/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
}
Expand Down Expand Up @@ -152,6 +161,7 @@ const react = (_options?: Options): PluginOption[] => {
result.map!,
'@vitejs/plugin-react-swc',
id,
options.reactRefreshHost,
)
},
},
Expand Down
12 changes: 12 additions & 0 deletions packages/plugin-react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions packages/plugin-react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
9 changes: 9 additions & 0 deletions packages/plugin-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down Expand Up @@ -263,6 +271,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
result.map!,
'@vitejs/plugin-react',
id,
opts.reactRefreshHost
)
}
},
Expand Down
Loading