基本上完成了对于SSR的实验,但CSS Module的实验未完成。
This commit is contained in:
		
							
								
								
									
										24
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								index.html
									
									
									
									
									
								
							| @@ -1,13 +1,15 @@ | ||||
| <!doctype html> | ||||
| <html lang="en"> | ||||
|   <head> | ||||
|     <meta charset="UTF-8" /> | ||||
|     <link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Vite + React + TS</title> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div id="root"></div> | ||||
|     <script type="module" src="/src/main.tsx"></script> | ||||
|   </body> | ||||
| <html lang="zh-CN"> | ||||
|  | ||||
| <head> | ||||
|   <meta charset="UTF-8" /> | ||||
|   <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|   <title>Vite + React + TS</title> | ||||
| </head> | ||||
|  | ||||
| <body> | ||||
|   <div id="root"><!--ssr-outlet--></div> | ||||
|   <script type="module" src="/src/main.tsx"></script> | ||||
| </body> | ||||
|  | ||||
| </html> | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@elysiajs/static": "^1.1.1", | ||||
|     "clsx": "^2.1.1", | ||||
|     "elysia": "^1.1.26", | ||||
|     "elysia-connect-middleware": "^0.0.3", | ||||
|     "react": "^19.0.0", | ||||
|   | ||||
							
								
								
									
										25
									
								
								server.ts
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								server.ts
									
									
									
									
									
								
							| @@ -1,20 +1,37 @@ | ||||
| import Elysia from 'elysia'; | ||||
| import { connect } from 'elysia-connect-middleware'; | ||||
| import { createElement } from 'react'; | ||||
| import { renderToReadableStream } from 'react-dom/server'; | ||||
| import { renderToString } from 'react-dom/server'; | ||||
| import { createServer } from 'vite'; | ||||
| 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 vite = await createServer({ | ||||
|   server: { middlewareMode: true }, | ||||
|   appType: 'custom', | ||||
| }); | ||||
| app.use(connect(vite.middlewares)); | ||||
| app.get('/', async () => { | ||||
| app.get('/', async ({ request }) => { | ||||
|   const url = request.url.replace(base, ''); | ||||
|   const app = createElement(App); | ||||
|   const stream = await renderToReadableStream(app, { bootstrapScripts: ['/src/main.tsx'] }); | ||||
|   return new Response(stream, { | ||||
|   const rootComponent = await renderToString(app); | ||||
|  | ||||
|   if (!isProduction) { | ||||
|     template = await vite.transformIndexHtml(url, template); | ||||
|   } | ||||
|  | ||||
|   const html = template.replace(`<!--ssr-outlet-->`, () => rootComponent); | ||||
|  | ||||
|   return new Response(html, { | ||||
|     headers: { | ||||
|       'Content-Type': 'text/html', | ||||
|     }, | ||||
|   | ||||
							
								
								
									
										20
									
								
								src/App.tsx
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/App.tsx
									
									
									
									
									
								
							| @@ -6,21 +6,11 @@ import { MainLayout } from './pages/MainLayout'; | ||||
| export const App = () => { | ||||
|   return ( | ||||
|     <StrictMode> | ||||
|       <html lang="zh-CN"> | ||||
|         <head> | ||||
|           <meta charSet="utf-8" /> | ||||
|           <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||
|           <title>React SSR App</title> | ||||
|           <link rel="stylesheet" href="/src/index.css" /> | ||||
|         </head> | ||||
|         <body> | ||||
|           <StaticRouter> | ||||
|             <Routes> | ||||
|               <Route path="/" element={<MainLayout />} /> | ||||
|             </Routes> | ||||
|           </StaticRouter> | ||||
|         </body> | ||||
|       </html> | ||||
|       <StaticRouter> | ||||
|         <Routes> | ||||
|           <Route path="/" element={<MainLayout />} /> | ||||
|         </Routes> | ||||
|       </StaticRouter> | ||||
|     </StrictMode> | ||||
|   ); | ||||
| }; | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| // Boot styles | ||||
| // import './index.css'; | ||||
| import './index.css'; | ||||
|  | ||||
| // Boot scripts | ||||
| import { hydrateRoot } from 'react-dom/client'; | ||||
| 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 styles from './MainLayout.module.css'; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user