
手动实现
// 服务器端(Node.js + Express)
import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from './App';
const app = express();
app.get('/', (req, res) => {
const html = renderToString(<App />);
res.send(`
<!DOCTYPE html>
<html>
<head><title>SSR Demo</title></head>
<body>
<div id="root">${html}</div>
<script src="/client.js"></script> <!-- 客户端 hydrate -->
</body>
</html>
`);
});
app.listen(3000);
// pages/index.js
import React from 'react';
使用next.js
// 服务端数据获取(SSR)
export async function getServerSideProps() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return { props: { data } }; // 数据注入组件 props
}
// 页面组件
export default function Home({ data }) {
return (
<div>
<h1>{data.title}</h1>
<p>{data.description}</p>
</div>
);
}
HTML 生成流程
用户访问页面:浏览器请求 /。
服务器执行:
Next.js 服务器检测到 pages/index.js 导出了 getServerSideProps。
调用该函数获取数据,等待数据返回。
渲染 HTML:
将数据作为 props 传递给 Home 组件。
使用 ReactDOMServer.renderToString() 生成组件 HTML 字符串。
返回完整 HTML:
将渲染结果嵌入到模板中,包含:
初始数据(通过 __NEXT_DATA__ 注入)。
客户端 Hydration 脚本。
<!DOCTYPE html>
<html>
<body>
<div id="__next">
<!-- 服务端渲染的 HTML 内容 -->
<div>
<h1>Hello World</h1>
<p>This is SSR content.</p>
</div>
</div>
<!-- 客户端激活脚本 -->
<script src="/_next/static/chunks/main.js"></script>
<script>
self.__NEXT_DATA__ = { props: { data: { title: "Hello World" } } };
</script>
</body>
</html>
浏览器下载 JS 后,React 会“激活”静态 HTML,使其可交互。