服务端渲染(Server-Side Rendering)指在服务器端完成页面DOM构建的技术方案。其发展历程可分为三个阶段:
阶段 | 时期 | 典型技术 |
---|---|---|
传统SSR | 2000-2010 | JSP/PHP |
现代SSR | 2015-2020 | Next.js/Nuxt.js |
混合渲染 | 2020-至今 | Qwik/Astro |
const express = require('express');
const React = require('react');
const { renderToString } = require('react-dom/server');
const app = express();
// 服务端路由处理
app.get('/ssr-demo', (req, res) => {
const reactApp = renderToString(<App />);
const htmlTemplate = `
SSR Demo
${reactApp}
`;
res.send(htmlTemplate);
});
app.listen(3000, () => {
console.log('SSR Server running on port 3000');
});
指标 | SSR方案 | CSR方案 | 提升幅度 |
---|---|---|---|
FCP | 1.2s | 3.8s | 316% |
TTI | 2.1s | 1.9s | -9.5% |
SEO评分 | 98 | 65 | +33分 |
客户端渲染(CSR)流程:
服务端渲染(SSR)流程:
框架,类型,SSR方案, hydration方式,流式渲染
Next.js,React,内置,渐进式 hydration,支持
Nuxt.js,Vue,内置,组件级 hydration,支持
Angular Universal,Angular,独立包,整体 hydration,不支持
SvelteKit,Svelte,内置,选择性 hydration,支持
/my-app
├── app
│ ├── layout.tsx
│ ├── page.tsx
│ └── api
│ └── data/route.ts
├── public
│ └── static
└── package.json
// app/page.tsx
async function fetchData() {
const res = await fetch('https://api.example.com/data');
return res.json();
}
export default async function Page() {
const data = await fetchData();
return (
<main>
<h1>{data.title}</h1>
<p>{data.content}</p>
</main>
)
}
+-----------------+
| CDN Edge |
| (缓存HTML) |
+--------+--------+
|
+--------v--------+
| Load Balancer |
+--------+--------+
|
+---------------+---------------+
| | |
+-------v-------+ +-----v------+ +------v------+
| Node.js | | Node.js | | Node.js |
| SSR Server | | SSR Server | | SSR Server |
+---------------+ +------------+ +------------+
# Nginx配置示例
location / {
proxy_cache ssr_cache;
proxy_pass http://ssr_backend;
proxy_cache_valid 200 302 10m;
proxy_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache-Status $upstream_cache_status;
}
预加载资源// 全局错误边界
class SSRErrorBoundary extends React.Component {
componentDidCatch(error) {
sendErrorToMonitoring(error);
this.setState({ hasError: true });
}
render() {
if (this.state.hasError) {
return <FallbackUI />;
}
return this.props.children;
}
}
场景 | 推荐方案 | 核心优势 |
---|---|---|
电商详情页 | Next.js + CDN缓存 | SEO友好 + 高并发承载 |
管理后台 | Vite + CSR | 开发效率高 + 交互流畅 |
文档站点 | Astro + 部分SSR | 按需水合 + 极速加载 |
高交互Web应用 | Qwik + 延迟加载 | 瞬时交互 + 极低TTI |
Q:SSR如何实现用户状态同步?
A:推荐采用Cookie + 服务端状态注入方案:
// 服务端获取状态
const cookies = parseCookies(req);
const store = createStore({ user: cookies.user });
// 客户端同步
window.__INITIAL_STATE__ = ${JSON.stringify(store.getState())};
Q:如何处理SSR中的异步依赖?
A:使用@loadable/component
实现按需加载:
import loadable from '@loadable/component';
const AsyncComponent = loadable(() => import('./HeavyComponent'), {
fallback: <Loading />
});