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

如何在ReactJS中仅对指定路由进行服务端渲染?

可以仅对特定React路由实现服务端渲染吗?

当然可以,你完全能用react-dom/server只对指定路由(比如你的/post)做服务端渲染,其他路由(比如/home)保持客户端渲染。下面是具体的实现思路和关键步骤:

核心思路

在服务端(以Node.js + Express为例)配置路由匹配逻辑:当请求命中/post/:id时,触发SSR流程;其他请求直接返回客户端渲染的基础HTML文件。

关键步骤

1. 服务端路由匹配与SSR处理

import express from 'express';
import path from 'path';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom/server';
import React from 'react';
import App from '../src/App';
import { getPostById } from './db'; // 自定义的数据库查询方法

const app = express();

// 托管前端打包后的静态资源
app.use(express.static(path.resolve(__dirname, '../build')));

// 处理需要SSR的/post路由
app.get('/post/:id', async (req, res) => {
  const postId = req.params.id;
  try {
    // 先从数据库获取文章内容
    const postData = await getPostById(postId);
    
    // 用StaticRouter在服务端渲染React组件
    const serverRenderedHtml = renderToString(
      <StaticRouter location={req.url} context={{}}>
        <App initialPostData={postData} />
      </StaticRouter>
    );

    // 把渲染后的HTML插入到基础模板中
    const finalHtml = `
      <!DOCTYPE html>
      <html lang="zh-CN">
        <head>
          <meta charset="UTF-8">
          <title>${postData.title}</title>
        </head>
        <body>
          <div id="root">${serverRenderedHtml}</div>
          <script>
            // 将服务端获取的数据注入客户端,避免重复请求
            window.__INITIAL_POST_DATA__ = ${JSON.stringify(postData)}
          </script>
          <script src="/static/js/main.js"></script>
        </body>
      </html>
    `;
    res.send(finalHtml);
  } catch (err) {
    // 处理文章不存在或查询失败的情况
    res.status(404).send('<h1>文章不存在</h1>');
  }
});

// 其他路由返回客户端渲染的基础HTML
app.get('*', (req, res) => {
  res.sendFile(path.resolve(__dirname, '../build', 'index.html'));
});

app.listen(3000, () => {
  console.log('服务启动在3000端口');
});

2. 客户端路由与数据复用

在客户端入口文件中,读取服务端注入的初始数据并传入组件:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './Home';
import Post from './Post';

function App({ initialPostData }) {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/home" element={<Home />} />
        <Route 
          path="/post/:id" 
          element={<Post initialData={initialPostData} />} 
        />
      </Routes>
    </BrowserRouter>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
// 从全局变量获取服务端注入的初始数据
root.render(
  <App initialPostData={window.__INITIAL_POST_DATA__ || null} />
);

3. Post组件的逻辑处理

优先使用服务端传入的初始数据,无数据时再发起客户端请求:

import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { getPostById } from './api';

function Post({ initialData }) {
  const { id } = useParams();
  const [post, setPost] = useState(initialData);

  useEffect(() => {
    // 仅在没有初始数据时发起客户端请求
    if (!post) {
      getPostById(id).then(data => setPost(data));
    }
  }, [id, post]);

  if (!post) return <div>加载中...</div>;

  return (
    <div className="post-detail">
      <h1>{post.title}</h1>
      <div className="post-content">{post.content}</div>
    </div>
  );
}

export default Post;

注意事项

  • 确保服务端与客户端的路由配置完全一致,避免出现路由不匹配的问题。
  • 服务端注入的数据要做JSON序列化处理,避免XSS风险。
  • 做好错误边界处理,防止SSR过程中出现异常导致服务崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 07:45:38