Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
65622e08e5 | ||
|
a0dbe4f7fc | ||
|
dbaee0c81a | ||
|
d6aa2782bf |
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -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
|
||||||
|
|
24
index.html
24
index.html
|
@ -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>
|
||||||
|
|
|
@ -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",
|
||||||
|
|
24
server.ts
24
server.ts
|
@ -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',
|
||||||
},
|
},
|
||||||
|
|
20
src/App.tsx
20
src/App.tsx
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 />);
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user