This commit is contained in:
2026-04-14 11:25:25 +08:00
parent 4cf060136d
commit a0c48937ad
9 changed files with 94 additions and 23 deletions

View File

@@ -1,14 +1,6 @@
// entry.tsx - 客户端入口
import { hydrateRoot, createRoot } from 'react-dom/client';
import { hydrateRoot } from 'react-dom/client';
import A from './pages/a/index';
const root = document.getElementById('root');
createRoot(root!).render(<A />);
// hydrateRoot(document.getElementById('root')!, <A />);
setTimeout(() => {
console.log('Hydrating with new content...');
hydrateRoot(root!, <A />);
}, 30000)
// React 19: renderToPipeableStream embeds RSC payload in HTML
// hydrateRoot will find and use that payload automatically
hydrateRoot(document.getElementById('root')!, <A />);

View File

@@ -1,15 +1,17 @@
import { renderToString } from 'react-dom/server';
import { renderToReadableStream } from 'react-dom/server';
import A from './pages/a/index';
import http from 'http';
const html = renderToString(<A />, {
identifierPrefix: 'test-',
Bun.serve({
port: 3000,
async fetch(req) {
const stream = await renderToReadableStream(<A />, {
bootstrapScripts: [],
});
return new Response(stream, {
headers: { 'Content-Type': 'text/html' },
});
},
});
console.log(html);
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(html);
}).listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
console.log('Server running on http://localhost:3000');

View File

@@ -1,3 +1,4 @@
"use client";
import { useEffect } from "react";
export default function List() {

View File

@@ -0,0 +1,8 @@
// Server component - no 'use client' directive
export default function ServerList() {
return (
<div>
<h1>Server List</h1>
</div>
);
}

View File

@@ -0,0 +1,18 @@
'use server';
import { useEffect } from "react";
const getVersion = async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
return '1.0.0';
}
export default async function List() {
const v = await getVersion();
return (
<div>
<h1>List - Version {v}</h1>
<div style={{
width: 200
}}>Primary Button</div>
</div>
);
}

31
src/server-node.tsx Normal file
View File

@@ -0,0 +1,31 @@
"use server";
import { renderToPipeableStream, renderToString } from 'react-dom/server';
// import A from './pages/a/index.tsx';
import { AEntry } from './browser-entry.tsx';
import AServer from './pages/a/server/index.tsx';
import http from 'http';
const PORT = 3000;
http.createServer((req, res) => {
if (req.url === '/ssr') {
const { pipe } = renderToPipeableStream(<AServer />, {
bootstrapScripts: [],
onShellReady() {
res.writeHead(200, { 'Content-Type': 'text/html' });
pipe(res);
},
onShellError(err) {
console.error('Shell error:', err);
res.writeHead(500);
res.end('Server Error');
}
});
} else {
const str = renderToString(<A />);
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(str);
}
}).listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});