Vite+React SSR配置异常:访问本地服务时浏览器无响应
Vite React SSR 服务端无响应问题排查
问题描述
我正在尝试基于Vite实现React SSR(服务端渲染),过程中遇到了问题:server.js可以正常启动(但存在警告),当访问本地服务localhost:3001时,浏览器一直处于加载状态,无法获取响应。
我在server.js中使用了h3、sirv和listhen工具,同时搭配react-router-dom 6.4。在await前添加console.log可以正常输出,说明服务在等待HTTP请求,但浏览器始终没有收到响应。我怀疑问题出在server.js中,现已附上相关代码及运行npm run dev时的终端输出,想请教哪里配置出错了?是否和server.js中的异步代码有关?
假设你的server.js核心代码如下:
import { createApp, defineEventHandler, createRouter } from 'h3' import { renderToString } from 'react-dom/server' import { StaticRouterProvider, createStaticHandler, createMemoryRouter } from 'react-router-dom/server' import sirv from 'sirv' import { listen } from 'listhen' import App from './src/App' const app = createApp() app.use(sirv('dist/client', { dev: true })) const router = createRouter() router.get('*', defineEventHandler(async (event) => { const staticHandler = createStaticHandler(App.routes) const context = await staticHandler.query({ request: event.node.req }) const memoryRouter = createMemoryRouter(App.routes, { initialEntries: [event.node.req.url], initialIndex: 0 }) const html = renderToString( <StaticRouterProvider router={memoryRouter} context={context} /> ) // 此处可能未返回响应 })) app.use(router) listen(toNodeListener(app), { port: 3001 })
终端运行输出示例:
> npm run dev > dev > node server.js Listening on http://localhost:3001 (node:12345) Warning: Some warning message here (Use `node --trace-warnings ...` to show where the warning was created)
核心问题排查与修复
1. 未主动返回HTTP响应
这是最常见的原因:你的代码执行了renderToString生成HTML,但没有调用h3的send()方法或event.res.end()结束请求,导致浏览器一直等待响应。
修复方式:在路由处理函数末尾添加响应返回逻辑:
return send(event, ` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>React SSR</title> </head> <body> <div id="root">${html}</div> <script type="module" src="/src/client.js"></script> </body> </html> `, { headers: { 'Content-Type': 'text/html; charset=utf-8' } })
2. React Router 6.4 服务端逻辑遗漏
使用createStaticHandler和createMemoryRouter时,必须处理重定向、404等场景,否则请求会被挂起:
// 处理重定向 if (context.status === 301 || context.status === 302) { event.node.res.writeHead(context.status, { Location: context.headers.get('Location') }) event.node.res.end() return } // 处理404 if (context.status === 404) { event.node.res.writeHead(404) event.node.res.end('<h1>404 Not Found</h1>') return }
3. 异步代码未捕获错误
如果路由处理函数中有未捕获的异步错误,会导致请求无响应。添加try/catch块捕获并返回错误响应:
router.get('*', defineEventHandler(async (event) => { try { // 现有SSR逻辑 } catch (err) { console.error('SSR渲染错误:', err) event.node.res.writeHead(500) event.node.res.end('<h1>Internal Server Error</h1>') } }))
4. 静态文件服务与路由顺序错误
确保静态文件服务的app.use(sirv(...))放在路由处理之前,否则静态资源请求会被路由捕获,导致客户端脚本无法加载:
// 先挂载静态文件服务 app.use(sirv('dist/client', { dev: true })) // 再挂载路由 app.use(router)
修复后完整路由处理示例
router.get('*', defineEventHandler(async (event) => { try { const staticHandler = createStaticHandler(App.routes) const context = await staticHandler.query({ request: event.node.req, params: event.params }) // 处理重定向 if (context.status === 301 || context.status === 302) { event.node.res.writeHead(context.status, { Location: context.headers.get('Location') }) event.node.res.end() return } // 处理404 if (context.status === 404) { event.node.res.writeHead(404) event.node.res.end('<h1>404 Not Found</h1>') return } const memoryRouter = createMemoryRouter(App.routes, { initialEntries: [event.node.req.url], initialIndex: 0 }) const html = renderToString( <StaticRouterProvider router={memoryRouter} context={context} /> ) // 返回完整HTML return send(event, ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>React SSR App</title> </head> <body> <div id="root">${html}</div> <script type="module" src="/src/main.jsx"></script> </body> </html> `, { headers: { 'Content-Type': 'text/html; charset=utf-8' } }) } catch (err) { console.error('SSR Error:', err) event.node.res.writeHead(500) event.node.res.end('<h1>Internal Server Error</h1>') } }))
额外调试建议
- 打开浏览器开发者工具的网络面板,查看请求状态码和响应内容,确认是服务端未返回响应还是返回了错误内容
- 检查终端是否有未捕获的错误日志,异步错误可能没有被自动打印
- 验证Vite客户端构建配置,确保客户端脚本路径正确可访问
内容的提问来源于stack exchange,提问作者Peter Devlin
相关产品推荐
相关产品推荐

