演示
工具演示页面
什么是 SSR?
Demo 页面不是面向普通用户的实用工具,而是一个用于验证服务端渲染链路的小型参考页面。它展示 Next.js App Router 页面如何在服务端获取数据,把结果直接渲染进首屏 HTML,同时加载当前语言的本地化文案。这个页面适合检查公共基础设施是否正常:环境变量、服务端签名请求、API 返回结构、locale 路由和翻译加载。它能正常工作,说明基础 SSR 路径大体健康,再去排查复杂工具页会更有方向;如果它失败,问题通常在公共服务端配置或 API 连通性。Demo 页应保持简单,这样才能作为部署和框架改动后的烟雾测试。
使用方法
使用方法
- 页面在服务端自动调用后端 API
- HTML 包含预渲染内容,无需客户端请求
- 查看 API 返回的数据
- 适合需要 SEO 优化的页面
开发说明
- 将此页面作为 SSR、语言加载、服务端签名请求和 API 连通的冒烟测试。
- 如果此页面无法加载,请先检查共享服务器配置,再排查具体工具页面。
使用场景
技术原理
此 Demo 页面基于 Next.js 16 App Router 构建,默认使用服务端渲染(SSR)。当用户请求页面时,Node.js 服务器首先运行 React 组件,调用后端 API 获取数据,然后将完整渲染的 HTML 在单次响应中返回浏览器。浏览器立即开始解析和绘制 HTML,因此用户在第一帧就能看到完整内容,无需等待 JavaScript 下载和执行。 这与传统的客户端渲染(CSR)形成鲜明对比。在 CSR 下,服务器只返回一个近乎空白的 HTML 壳和一个 JS 链接;浏览器必须下载 JS 包、运行框架初始化、调用 API 获取数据,然后才能渲染页面。从用户角度来看,这就是"空白屏幕等待期",对搜索引擎爬虫来说更糟——大多数爬虫不执行 JavaScript,只能看到空壳。 SSR 之后,Next.js 还会注入一段 JavaScript 进行"水合"(hydration):将现有 DOM 与 React 组件树关联并绑定事件监听器,使页面变得可交互。完整流程是 HTML 解析 -> CSS 加载 -> JS 下载 -> 水合 -> 可交互。在三个核心 Web 指标中,LCP(最大内容绘制)和 CLS(累积布局偏移)在 SSR 下通常表现更好,而 INP(交互到下次绘制)取决于水合速度和事件处理程序的实现质量。
- Next.js App Router:App Router 中的页面默认是 Server Component,在服务器上运行并自动返回 HTML,无需额外配置。
- SSR vs CSR:SSR 以服务器资源为代价提供快速首次绘制和 SEO 友好性;CSR 适合不需要 SEO 的内部仪表盘和其他交互场景。
- 首次绘制流程:HTML 解析 -> CSS 加载和渲染 -> JS 下载和执行 -> React 水合 -> 页面可交互;每一步都影响 LCP。
- SEO 爬虫友好性:Googlebot 和 Bingbot 等主流爬虫直接读取 HTML 文本;SSR 输出完整内容保证了爬取覆盖率。
- Web Vitals 阈值:LCP < 2.5s、INP < 200ms、CLS < 0.1 是 Google 推荐的"良好"阈值;SSR 使达到 LCP 和 CLS 更容易。
- 签名请求:Demo 页面在服务端通过 serverApiFetch 调用后端 API,自动携带 X-Timestamp、X-Nonce 和 X-Sign 完成鉴权。
示例
SSR(服务端渲染)
// app/page.tsx(默认是 Server Component)
export default async function Page() {
const data = await fetch('/api/info').then(r => r.json());
return <div>{data.title}</div>;
}
// 返回的 HTML 已经直接包含 <div>真实内容</div>CSR(客户端渲染)
'use client';
import { useEffect, useState } from 'react';
export default function Page() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/info').then(r => r.json()).then(setData);
}, []);
return <div>{data?.title || 'Loading...'}</div>;
}
// 首屏 HTML 中只包含 <div>Loading...</div>首屏速度对比
# SSR
FCP: 0.4s LCP: 0.8s TTI: 1.2s
SEO: 爬虫直接拿到完整内容
# CSR
FCP: 0.6s LCP: 1.8s TTI: 2.4s
SEO: 爬虫需要执行 JS 才能拿到内容常见问题
这个 demo 页面到底是在演示什么?
这是一个服务端渲染(SSR)的参考路由,演示 Next.js App Router 页面如何在服务端拉取数据、把结果嵌入首屏 HTML、同时还能正确加载本地化文案。它不是面向用户的工具,而是给开发者用的冒烟测试。
数据是在服务端还是在浏览器拉取的?
在服务端。页面在 React Server Component 内调用 serverApiFetch(携带 src/lib/sign.ts 中的签名请求头),浏览器收到的 HTML 已经包含数据,首屏不会再发起客户端请求。
为什么有时页面显示的数据是旧的?
Next.js 可能根据 revalidate 配置缓存 SSR 响应。如果每次请求都要拿到新数据,可设置 export const dynamic = "force-dynamic",或在 fetch 中传入 {cache: 'no-store'}。该 demo 路由保留默认行为以保持示例简洁。
可以照搬这种写法到自己的页面吗?
可以——这正是它的用途。该路由演示了如何把 next-intl 的 getTranslations 与服务端数据拉取结合,并把结果传给 Client Component 完成交互。复制 layout.tsx 与 page.tsx 后替换数据源即可。
为什么内部 API 也要做请求签名?
X-Timestamp / X-Nonce / X-Sign 用于防重放,并确保来自公网的请求确实出自可信客户端。签名密钥对登录用户使用按会话生成的 sessionKey,否则使用默认 key;具体实现见 src/lib/sign.ts 与 src/lib/fetch.ts。
这个页面会出现在生产构建里吗?
会作为参考代码部署在线上,但首页和工具列表都不会链接到它,也不作为面向用户的工具宣传。可以把它当成以路由形式呈现的开发者文档。
想了解项目结构应该先看哪些文件?
先看本页的 layout.tsx 与 page.tsx,再阅读 src/i18n.ts(语言配置)、src/i18n/request.ts(全局翻译加载)、src/lib/load-page-messages.ts(按页加载翻译)以及 src/lib/fetch.ts(带签名的请求封装)。