You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Vite SSR使用react-router-dom路由遇document未定义等错误求助

React Vite SSR 路由问题解决方案

核心问题分析

  1. document is not defined 错误:服务端渲染(SSR)处于 Node.js 环境,不存在浏览器的 document 对象,但 BrowserRouter/createBrowserRouter 依赖浏览器环境创建 history,在服务端执行这类代码会直接报错。
  2. useRoutes() 需在 Router 上下文 错误:移除浏览器端路由组件后,客户端缺少 Router 上下文提供,导致路由无法正常解析。

分步解决方案

1. 抽离共享路由配置

创建单独的 src/routes.js 文件,统一定义路由结构,确保服务端和客户端路由规则完全一致:

import { Home } from './pages/Home';
import { Other } from './pages/Other';
import { NotFound } from './pages/NotFound';
import App from './App';

export const routes = [
  {
    path: '/',
    element: <App />,
    errorElement: <NotFound />,
    children: [
      { index: true, element: <Home /> }, // 根路由匹配Home页面
      { path: 'other', element: <Other /> }, // "关于我们"等其他页面路由
    ],
  },
];

2. 修改共享路由入口组件 (src/index.jsx)

改为使用 useRoutes 渲染路由,依赖外层提供的 Router 上下文(服务端用 StaticRouter,客户端用 BrowserRouter):

import React from 'react';
import { useRoutes } from 'react-router-dom';
import { routes } from './routes';

export const Index = () => {
  const routeElement = useRoutes(routes);
  return routeElement;
};

3. 修复服务端渲染入口 (src/entry-server.jsx)

使用服务端专用的 StaticRouter,传入请求 URL 确保服务端渲染对应路由内容:

import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { StaticRouter } from 'react-router-dom/server';
import { Index } from '.';

export function render(url) {
  const html = ReactDOMServer.renderToString(
    <StaticRouter location={url}>
      <Index />
    </StaticRouter>
  );
  return { html };
}

4. 修复客户端渲染入口 (src/entry-client.jsx)

使用浏览器端专用的 BrowserRouter 提供路由上下文,确保客户端路由正常工作:

import './index.css';
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { Index } from './index';

ReactDOM.hydrateRoot(
  document.getElementById('root'),
  <React.StrictMode>
    <BrowserRouter>
      <Index />
    </BrowserRouter>
  </React.StrictMode>
);

可选:使用 RouterProvider 替代 BrowserRouter

如果偏好 React Router v6.4+ 的 RouterProvider 写法,可修改客户端入口为:

import './index.css';
import React from 'react';
import ReactDOM from 'react-dom/client';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import { routes } from './routes';

// 仅在客户端执行,依赖浏览器环境
const router = createBrowserRouter(routes);

ReactDOM.hydrateRoot(
  document.getElementById('root'),
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

此时 src/index.jsx 可直接删除,无需额外的共享组件。

关键注意事项

  • 服务端永远不要使用依赖浏览器 API 的路由组件(BrowserRouter/createBrowserRouter),必须用 StaticRouter。
  • 客户端和服务端的路由配置必须完全一致,避免 hydration 不匹配问题。
  • 404 页面(NotFound)不要包含浏览器专属 API(如 window/document),否则服务端渲染会报错。

内容的提问来源于stack exchange,提问作者Pablo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 00:07:02