Compare commits

..

4 Commits

Author SHA1 Message Date
徐涛
65622e08e5 更改一下服务的监听端口。 2024-12-16 16:09:56 +08:00
徐涛
a0dbe4f7fc 切换到使用renderToReadableStream渲染根组件。 2024-12-16 15:18:42 +08:00
徐涛
dbaee0c81a 基本上完成了对于SSR的实验,但CSS Module的实验未完成。 2024-12-15 07:49:18 +08:00
徐涛
d6aa2782bf 补充丢失的样式文件。 2024-12-13 16:57:42 +08:00
8 changed files with 45 additions and 31 deletions

1
.gitignore vendored
View File

@ -1030,4 +1030,5 @@ _site/
# Details at https://github.com/github/pages-gem/issues/768 # Details at https://github.com/github/pages-gem/issues/768
Gemfile.lock Gemfile.lock
# Fix extra-ignoring for kernel module file pattern on CSS Module files.
!*.module.css !*.module.css

BIN
bun.lockb

Binary file not shown.

View File

@ -1,13 +1,15 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="zh-CN">
<head>
<meta charset="UTF-8" /> <head>
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title> <title>Vite + React + TS</title>
</head> </head>
<body>
<div id="root"></div> <body>
<script type="module" src="/src/main.tsx"></script> <div id="root"><!--ssr-outlet--></div>
</body> <script type="module" src="/src/main.tsx"></script>
</body>
</html> </html>

View File

@ -11,6 +11,7 @@
}, },
"dependencies": { "dependencies": {
"@elysiajs/static": "^1.1.1", "@elysiajs/static": "^1.1.1",
"clsx": "^2.1.1",
"elysia": "^1.1.26", "elysia": "^1.1.26",
"elysia-connect-middleware": "^0.0.3", "elysia-connect-middleware": "^0.0.3",
"react": "^19.0.0", "react": "^19.0.0",

View File

@ -5,16 +5,34 @@ import { renderToReadableStream } from 'react-dom/server';
import { createServer } from 'vite'; import { createServer } from 'vite';
import { App } from './src/App'; import { App } from './src/App';
const isProduction = process.env.NODE_ENV === 'production';
const base = process.env.BASE || '/';
let template = '';
if (!isProduction) {
const templateFile = Bun.file('index.html');
template = await templateFile.text();
}
const app = new Elysia(); const app = new Elysia();
const vite = await createServer({ const vite = await createServer({
server: { middlewareMode: true }, server: { middlewareMode: true },
appType: 'custom', appType: 'custom',
}); });
app.use(connect(vite.middlewares)); app.use(connect(vite.middlewares));
app.get('/', async () => { app.get('/', async ({ request }) => {
const url = request.url.replace(base, '');
const app = createElement(App); const app = createElement(App);
const stream = await renderToReadableStream(app, { bootstrapScripts: ['/src/main.tsx'] }); const rootComponent = await renderToReadableStream(app);
return new Response(stream, { const rootComponentString = await Bun.readableStreamToText(rootComponent);
if (!isProduction) {
template = await vite.transformIndexHtml(url, template);
}
const html = template.replace(`<!--ssr-outlet-->`, () => rootComponentString);
return new Response(html, {
headers: { headers: {
'Content-Type': 'text/html', 'Content-Type': 'text/html',
}, },

View File

@ -6,21 +6,11 @@ import { MainLayout } from './pages/MainLayout';
export const App = () => { export const App = () => {
return ( return (
<StrictMode> <StrictMode>
<html lang="zh-CN"> <StaticRouter>
<head> <Routes>
<meta charSet="utf-8" /> <Route path="/" element={<MainLayout />} />
<meta name="viewport" content="width=device-width, initial-scale=1" /> </Routes>
<title>React SSR App</title> </StaticRouter>
<link rel="stylesheet" href="/src/index.css" />
</head>
<body>
<StaticRouter>
<Routes>
<Route path="/" element={<MainLayout />} />
</Routes>
</StaticRouter>
</body>
</html>
</StrictMode> </StrictMode>
); );
}; };

View File

@ -1,8 +1,8 @@
// Boot styles // Boot styles
// import './index.css'; import './index.css';
// Boot scripts // Boot scripts
import { hydrateRoot } from 'react-dom/client'; import { hydrateRoot } from 'react-dom/client';
import { App } from './App'; import { App } from './App';
hydrateRoot(document, <App />); hydrateRoot(document.getElementById('root'), <App />);

View File

@ -1,3 +1,5 @@
'use client';
import { Outlet } from 'react-router-dom'; import { Outlet } from 'react-router-dom';
import styles from './MainLayout.module.css'; import styles from './MainLayout.module.css';