Skip to content

Commit

Permalink
feat(plugin-react): allow to disable fast refresh (#3738)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjiahan authored Oct 16, 2024
1 parent d635625 commit 897ba03
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 16 deletions.
44 changes: 44 additions & 0 deletions e2e/cases/react/disable-fast-refresh/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import fs from 'node:fs';
import { join } from 'node:path';
import { dev, rspackOnlyTest } from '@e2e/helper';
import { expect, test } from '@playwright/test';

const cwd = __dirname;

rspackOnlyTest(
'HMR should work when Fast Refresh is disabled',
async ({ page }) => {
// HMR cases will fail in Windows
if (process.platform === 'win32') {
test.skip();
}

await fs.promises.cp(join(cwd, 'src'), join(cwd, 'test-temp-src'), {
recursive: true,
});

const rsbuild = await dev({
cwd,
page,
rsbuildConfig: {
source: {
entry: {
index: join(cwd, 'test-temp-src/index.ts'),
},
},
},
});

const locator = page.locator('#test');
await expect(locator).toHaveText('Hello Rsbuild!');
await expect(locator).toHaveCSS('color', 'rgb(255, 0, 0)');

const appPath = join(cwd, 'test-temp-src/App.tsx');
await fs.promises.writeFile(
appPath,
fs.readFileSync(appPath, 'utf-8').replace('Hello Rsbuild', 'Hello Test'),
);
await expect(locator).toHaveText('Hello Test!');
await rsbuild.close();
},
);
10 changes: 10 additions & 0 deletions e2e/cases/react/disable-fast-refresh/rsbuild.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';

export default defineConfig({
plugins: [
pluginReact({
fastRefresh: false,
}),
],
});
3 changes: 3 additions & 0 deletions e2e/cases/react/disable-fast-refresh/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#test {
color: rgb(255, 0, 0);
}
4 changes: 4 additions & 0 deletions e2e/cases/react/disable-fast-refresh/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import './App.css';

const App = () => <div id="test">Hello Rsbuild!</div>;
export default App;
9 changes: 9 additions & 0 deletions e2e/cases/react/disable-fast-refresh/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

const container = document.getElementById('root');
if (container) {
const root = createRoot(container);
root.render(React.createElement(App));
}
9 changes: 9 additions & 0 deletions e2e/cases/react/disable-fast-refresh/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "@rsbuild/config/tsconfig",
"compilerOptions": {
"jsx": "react-jsx",
"baseUrl": "./",
"outDir": "./dist"
},
"include": ["src"]
}
4 changes: 2 additions & 2 deletions e2e/cases/server/hmr/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ rspackOnlyTest('HMR should work by default', async ({ page }) => {
});

rspackOnlyTest(
'hmr should work when setting dev.port & client',
'HMR should work when setting dev.port & client',
async ({ page }) => {
// HMR cases will fail in Windows
if (process.platform === 'win32') {
Expand Down Expand Up @@ -116,7 +116,7 @@ rspackOnlyTest(
);

rspackOnlyTest(
'hmr should work when dev.port is `<port>`',
'HMR should work when dev.port is `<port>`',
async ({ page }) => {
// HMR cases will fail in Windows
if (process.platform === 'win32') {
Expand Down
27 changes: 20 additions & 7 deletions packages/plugin-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,38 @@ export type PluginReactOptions = {
* @see https://rspack.dev/guide/tech/react#rspackplugin-react-refresh
*/
reactRefreshOptions?: ReactRefreshOptions;
/**
* Whether to enable React Fast Refresh in development mode.
* @default true
*/
fastRefresh?: boolean;
};

export const PLUGIN_REACT_NAME = 'rsbuild:react';

export const pluginReact = ({
enableProfiler = false,
...options
}: PluginReactOptions = {}): RsbuildPlugin => ({
export const pluginReact = (
options: PluginReactOptions = {},
): RsbuildPlugin => ({
name: PLUGIN_REACT_NAME,

setup(api) {
const defaultOptions: PluginReactOptions = {
fastRefresh: true,
enableProfiler: false,
};
const finalOptions = {
...defaultOptions,
...options,
};

if (api.context.bundlerType === 'rspack') {
applyBasicReactSupport(api, options);
applyBasicReactSupport(api, finalOptions);

if (enableProfiler) {
if (finalOptions.enableProfiler) {
applyReactProfiler(api);
}
}

applySplitChunksRule(api, options?.splitChunks);
applySplitChunksRule(api, finalOptions?.splitChunks);
},
});
16 changes: 9 additions & 7 deletions packages/plugin-react/src/react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ export const applyBasicReactSupport = (
api: RsbuildPluginAPI,
options: PluginReactOptions,
): void => {
const REACT_REFRESH_PATH = require.resolve('react-refresh');
const REACT_REFRESH_PATH = options.fastRefresh
? require.resolve('react-refresh')
: '';

api.modifyEnvironmentConfig((userConfig, { mergeEnvironmentConfig }) => {
const isDev = userConfig.mode === 'development';
api.modifyEnvironmentConfig((config, { mergeEnvironmentConfig }) => {
const isDev = config.mode === 'development';
const usingHMR = isDev && config.dev.hmr && config.output.target === 'web';

const reactOptions: Rspack.SwcLoaderTransformConfig['react'] = {
development: isDev,
refresh:
isDev && userConfig.dev.hmr && userConfig.output.target === 'web',
refresh: usingHMR && options.fastRefresh,
runtime: 'automatic',
...options.swcReactOptions,
};
Expand All @@ -44,14 +46,14 @@ export const applyBasicReactSupport = (
},
};

return mergeEnvironmentConfig(extraConfig, userConfig);
return mergeEnvironmentConfig(extraConfig, config);
});

api.modifyBundlerChain(
async (chain, { CHAIN_ID, environment, isDev, target }) => {
const { config } = environment;
const usingHMR = isDev && config.dev.hmr && target === 'web';
if (!usingHMR) {
if (!usingHMR || !options.fastRefresh) {
return;
}

Expand Down
15 changes: 15 additions & 0 deletions website/docs/en/plugins/list/plugin-react.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,18 @@ pluginReact({
},
});
```

### fastRefresh

- **Type:** `boolean`
- **Default:** `true`

Whether to enable React [Fast Refresh](https://www.npmjs.com/package/react-refresh) in development mode.

If you need to disable Fast Refresh, you can set it to `false`:

```ts
pluginReact({
fastRefresh: false,
});
```
15 changes: 15 additions & 0 deletions website/docs/zh/plugins/list/plugin-react.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,18 @@ pluginReact({
},
});
```

### fastRefresh

- **类型:** `boolean`
- **默认值:** `true`

是否在开发模式下启用 React [Fast Refresh](https://www.npmjs.com/package/react-refresh)

如果你需要禁用 Fast Refresh,可以将其设置为 `false`

```ts
pluginReact({
fastRefresh: false,
});
```

0 comments on commit 897ba03

Please sign in to comment.