Skip to content

Commit ea048d2

Browse files
committed
chore: add examples/browser-mode
1 parent bb39264 commit ea048d2

File tree

15 files changed

+432
-0
lines changed

15 files changed

+432
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- https://github.com/kasperpeulen/vitest-plugin-rsc/
2+
- https://github.com/kasperpeulen/rsc-browser-vite-demo
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
7+
<script async type="module" src="/src/framework/main.tsx"></script>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
</body>
12+
</html>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "@vitejs/plugin-rsc-examples-browser-mode",
3+
"version": "0.0.0",
4+
"private": true,
5+
"license": "MIT",
6+
"type": "module",
7+
"scripts": {
8+
"dev": "vite",
9+
"build": "vite build",
10+
"preview": "vite preview"
11+
},
12+
"dependencies": {
13+
"@vitejs/plugin-rsc": "latest",
14+
"react": "^19.1.0",
15+
"react-dom": "^19.1.0"
16+
},
17+
"devDependencies": {
18+
"@types/react": "^19.1.8",
19+
"@types/react-dom": "^19.1.6",
20+
"@vitejs/plugin-react": "latest",
21+
"vite": "^7.0.6"
22+
}
23+
}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use server'
2+
3+
let serverCounter = 0
4+
5+
export async function getServerCounter() {
6+
return serverCounter
7+
}
8+
9+
export async function updateServerCounter(change: number) {
10+
serverCounter += change
11+
}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use client'
2+
3+
import React from 'react'
4+
5+
export function ClientCounter() {
6+
const [count, setCount] = React.useState(0)
7+
8+
return (
9+
<button onClick={() => setCount((count) => count + 1)}>
10+
Client Counter: {count}
11+
</button>
12+
)
13+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as React from 'react'
2+
import * as ReactDOMClient from 'react-dom/client'
3+
import * as ReactClient from '@vitejs/plugin-rsc/react/browser'
4+
import type { RscPayload } from './server'
5+
6+
export function render(rscStream: ReadableStream<Uint8Array>) {
7+
let rscPaylod: Promise<RscPayload>
8+
9+
function ClientRoot() {
10+
rscPaylod ??= ReactClient.createFromReadableStream<RscPayload>(rscStream)
11+
return React.use(rscPaylod).root
12+
}
13+
14+
const domRoot = document.getElementById('root')!
15+
const reactRoot = ReactDOMClient.createRoot(domRoot)
16+
reactRoot.render(
17+
<React.StrictMode>
18+
<ClientRoot />
19+
</React.StrictMode>,
20+
)
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './server'
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { renderToReadableStream } from '@vitejs/plugin-rsc/react/rsc'
2+
import type React from 'react'
3+
import { ESModulesEvaluator, ModuleRunner } from 'vite/module-runner'
4+
5+
export type RscPayload = {
6+
root: React.ReactNode
7+
}
8+
9+
async function main() {
10+
const rscRoot = (
11+
<div>
12+
<h1>RSC Browser Mode</h1>
13+
</div>
14+
)
15+
const rscStream = renderToReadableStream<RscPayload>({
16+
root: rscRoot,
17+
})
18+
19+
const clientRunner = createClientRunner()
20+
const clientEntry = await clientRunner.import<typeof import('./client')>(
21+
'/src/framework/client.tsx',
22+
)
23+
clientEntry.render(rscStream)
24+
}
25+
26+
function createClientRunner() {
27+
const runner = new ModuleRunner(
28+
{
29+
sourcemapInterceptor: false,
30+
transport: {
31+
invoke: async (payload) => {
32+
const response = await fetch(
33+
'/@vite/invoke-react-client?' +
34+
new URLSearchParams({
35+
data: JSON.stringify(payload),
36+
}),
37+
)
38+
return response.json()
39+
},
40+
},
41+
hmr: false,
42+
},
43+
new ESModulesEvaluator(),
44+
)
45+
return runner
46+
}
47+
48+
main()

0 commit comments

Comments
 (0)