Skip to content

Commit cfd2467

Browse files
authored
feat(plugin-preact): integrate @swc/plugin-prefresh to enhance prefresh (#3861)
1 parent 6f455f2 commit cfd2467

File tree

7 files changed

+129
-1
lines changed

7 files changed

+129
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
import { dev, rspackOnlyTest } from '@e2e/helper';
4+
import { expect, test } from '@playwright/test';
5+
6+
rspackOnlyTest(
7+
'HMR should work properly with `createContext`',
8+
async ({ page }) => {
9+
// HMR cases will fail in Windows
10+
if (process.platform === 'win32') {
11+
test.skip();
12+
}
13+
14+
const root = __dirname;
15+
const compFilePath = path.join(root, 'src/test-temp-B.jsx');
16+
const compSourceCode = `const B = (props) => {
17+
return <div id="B">B: {props.count}</div>;
18+
};
19+
20+
export default B;
21+
`;
22+
23+
fs.writeFileSync(compFilePath, compSourceCode, 'utf-8');
24+
25+
const rsbuild = await dev({
26+
cwd: root,
27+
page,
28+
});
29+
30+
const a = page.locator('#A');
31+
const b = page.locator('#B');
32+
33+
await expect(a).toHaveText('A: 0');
34+
await expect(b).toHaveText('B: 0');
35+
36+
await a.click({ clickCount: 5 });
37+
await expect(a).toHaveText('A: 5');
38+
await expect(b).toHaveText('B: 5');
39+
40+
// simulate a change to component B's source code
41+
fs.writeFileSync(
42+
compFilePath,
43+
compSourceCode.replace('B:', 'Beep:'),
44+
'utf-8',
45+
);
46+
47+
await page.waitForFunction(() => {
48+
const aText = document.querySelector('#A')!.textContent;
49+
const bText = document.querySelector('#B')!.textContent;
50+
51+
return (
52+
// the state (count) of A should be kept
53+
aText === 'A: 5' &&
54+
// content of B changed to `Beep: 5` means HMR has taken effect
55+
bText === 'Beep: 5'
56+
);
57+
});
58+
59+
await rsbuild.close();
60+
},
61+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { pluginPreact } from '@rsbuild/plugin-preact';
2+
3+
export default {
4+
plugins: [
5+
pluginPreact({
6+
exclude: [
7+
/node_modules/,
8+
// exclude Rsbuild internal HMR client
9+
/packages\/core\/dist/,
10+
],
11+
}),
12+
],
13+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { createContext } from 'preact';
2+
import { useContext, useState } from 'preact/hooks';
3+
import B from './test-temp-B';
4+
5+
const MyContext = createContext();
6+
7+
export const MyProvider = ({ children }) => {
8+
const [value, setValue] = useState(0);
9+
return (
10+
<MyContext.Provider value={{ value, setValue }}>
11+
{children}
12+
</MyContext.Provider>
13+
);
14+
};
15+
16+
const App = () => {
17+
const { value, setValue } = useContext(MyContext);
18+
return (
19+
<>
20+
<button id="A" type="button" onClick={() => setValue(value + 1)}>
21+
A: {value}
22+
</button>
23+
<B count={value} />
24+
</>
25+
);
26+
};
27+
28+
export default () => {
29+
return (
30+
<MyProvider>
31+
<App />
32+
</MyProvider>
33+
);
34+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { h, render } from 'preact';
2+
import A from './A';
3+
4+
render(h(A), document.getElementById('root'));

packages/plugin-preact/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"dependencies": {
2929
"@prefresh/core": "^1.5.2",
3030
"@prefresh/utils": "^1.2.0",
31-
"@rspack/plugin-preact-refresh": "^1.1.0"
31+
"@rspack/plugin-preact-refresh": "^1.1.0",
32+
"@swc/plugin-prefresh": "^3.0.3"
3233
},
3334
"devDependencies": {
3435
"@rsbuild/core": "workspace:*",

packages/plugin-preact/src/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ export const pluginPreact = (
6868
tools: {
6969
swc: {
7070
jsc: {
71+
experimental: {
72+
plugins: usePrefresh
73+
? [[require.resolve('@swc/plugin-prefresh'), {}]]
74+
: undefined,
75+
},
7176
parser: {
7277
syntax: 'typescript',
7378
// enable supports for JSX/TSX compilation

pnpm-lock.yaml

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)