Vite搭建React+TS项目用React-Router-Dom报document未定义错误
解决React Router + Vite SSR中
document is not defined的问题 错误原因
你遇到的ReferenceError: document is not defined是因为服务器端渲染(SSR)环境下不存在浏览器的document对象,但createBrowserRouter是专为浏览器环境设计的,它初始化时会直接访问document,导致Node.js服务器运行时触发报错。
解决方案
方案1:将路由初始化移到客户端组件内部
修改App.tsx,把路由创建逻辑放到组件内部,通过useEffect确保仅在浏览器环境执行:
import { RouterProvider, createBrowserRouter } from "react-router-dom"; import RootLayout from "./pages/Root"; import HomePage from "./pages/HomePage"; import BookDetail from "./pages/BookDetail"; import { useEffect, useState } from "react"; function App() { const [router, setRouter] = useState(null); useEffect(() => { // 仅在浏览器环境中创建浏览器路由 const browserRouter = createBrowserRouter([ { path: "/", element: <RootLayout />, children: [ { path: "/", element: <HomePage /> }, { path: "/book/:id", element: <BookDetail /> }, ], }, ]); setRouter(browserRouter); }, []); // 服务器端渲染时返回null,避免执行浏览器专属代码 if (!router) return null; return <RouterProvider router={router} />; } export default App;
方案2:使用React Router的SSR兼容路由方案
将路由配置抽离为共享文件,服务器端使用不依赖浏览器API的createMemoryRouter,客户端保持createBrowserRouter:
- 新建
routes.ts共享路由配置
import RootLayout from "./pages/Root"; import HomePage from "./pages/HomePage"; import BookDetail from "./pages/BookDetail"; export const routes = [ { path: "/", element: <RootLayout />, children: [ { path: "/", element: <HomePage /> }, { path: "/book/:id", element: <BookDetail /> }, ], }, ];
- 修改
App.tsx(客户端)
import { RouterProvider, createBrowserRouter } from "react-router-dom"; import { routes } from "./routes"; // 客户端正常使用浏览器路由 const router = createBrowserRouter(routes); function App() { return <RouterProvider router={router} />; } export default App;
- 修改
entry-server.tsx(服务器端)
import React from 'react' import ReactDOMServer from 'react-dom/server' import { createMemoryRouter, RouterProvider } from 'react-router-dom' import { routes } from './routes' export function render() { // 服务器端使用内存路由,不依赖浏览器document const router = createMemoryRouter(routes, { initialEntries: ["/"], // 可根据实际请求路径动态调整 }); const html = ReactDOMServer.renderToString( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> ) return { html } }
额外说明
两种方案核心都是让浏览器专属的路由逻辑只在客户端执行,避免服务器端渲染时访问不存在的浏览器API。如果你的项目不需要SSR,也可以直接删除entry-server.tsx相关配置,转为纯客户端渲染,同样能解决该问题。
内容的提问来源于stack exchange,提问作者Bogdan Deaconu
相关产品推荐
相关产品推荐

