React 服务端渲染:Next.js 基础
创建一个支持服务端渲染(SSR)的 React 应用,传统方式需要手动配置 Webpack、Babel 和 Node 服务器,过程繁琐且容易出错。Next.js 是一个基于 React 的轻量级框架,内置了 SSR、静态生成、路由系统和 API 路由等功能,能让你用最少的代码快速搭建高性能应用。
安装并启动项目
-
打开终端,执行以下命令创建新项目:
npx create-next-app@latest my-ssr-app -
按提示操作:
- 是否使用 TypeScript?选择
No(本指南使用 JavaScript)。 - 是否启用 ESLint?选择
Yes。 - 是否启用 Tailwind CSS?选择
No(避免干扰核心逻辑)。 - 是否使用
src/目录?选择Yes。 - 是否使用 App Router?选择
No(本指南基于 Pages Router,更适合理解 SSR 基础)。 - 是否自定义默认导入别名?选择
No。
- 是否使用 TypeScript?选择
-
进入项目目录并启动开发服务器:
cd my-ssr-app npm run dev -
打开浏览器访问
http://localhost:3000,你会看到默认欢迎页面。
理解 Pages Router 结构
Next.js 使用文件系统作为路由。在 src/pages 目录下:
index.js对应根路径/about.js对应/aboutuser/[id].js对应动态路径/user/123
删除 src/pages/index.js 中的默认内容,替换为以下最简页面:
// src/pages/index.js
export default function Home() {
return <h1>首页</h1>;
}
实现基础服务端渲染
Next.js 提供两个关键函数用于 SSR:getServerSideProps 和 getStaticProps。前者在每次请求时在服务端运行,后者在构建时运行(静态生成)。这里聚焦 getServerSideProps。
-
修改
src/pages/index.js,添加getServerSideProps:// src/pages/index.js export default function Home({ serverTime }) { return ( <div> <h1>首页</h1> <p>服务端渲染时间: {serverTime}</p> </div> ); } export async function getServerSideProps() { const serverTime = new Date().toISOString(); return { props: { serverTime, }, }; } -
刷新浏览器页面,你会看到当前服务器时间。多次刷新,时间会变化,证明每次请求都触发了服务端执行。
-
查看页面源代码(右键 → “查看页面源代码”),你会发现
<p>标签内已包含完整的时间字符串,而非空壳。这说明 HTML 是在服务端生成的,有利于 SEO 和首屏加载速度。
获取外部数据并渲染
真实场景中,SSR 常用于从数据库或 API 获取数据。下面模拟从外部接口获取用户信息。
-
创建一个模拟 API 函数(实际项目中替换为真实请求):
// src/lib/fetchUser.js export async function fetchUser(userId) { // 模拟网络延迟 await new Promise(resolve => setTimeout(resolve, 100)); return { id: userId, name: `用户 ${userId}`, email: `user${userId}@example.com`, }; } -
新建页面
src/pages/user/[id].js:// src/pages/user/[id].js import { fetchUser } from '../../lib/fetchUser'; export default function UserPage({ user }) { if (!user) { return <p>用户不存在</p>; } return ( <div> <h1>{user.name}</h1> <p>邮箱: {user.email}</p> </div> ); } export async function getServerSideProps({ params }) { const { id } = params; const user = await fetchUser(id); return { props: { user, }, }; } -
访问
http://localhost:3000/user/42,页面将显示“用户 42”的信息。URL 中的42通过params.id传入getServerSideProps。
处理错误与加载状态
getServerSideProps 在服务端运行,无法直接向用户展示“加载中”状态,但可以处理错误。
-
修改
fetchUser.js,使其在无效 ID 时抛出错误:// src/lib/fetchUser.js export async function fetchUser(userId) { await new Promise(resolve => setTimeout(resolve, 100)); if (userId < 1) { throw new Error('无效用户ID'); } return { id: userId, name: `用户 ${userId}`, email: `user${userId}@example.com`, }; } -
更新
getServerSideProps以捕获错误:// src/pages/user/[id].js(仅修改 getServerSideProps 部分) export async function getServerSideProps({ params }) { const { id } = params; try { const user = await fetchUser(Number(id)); return { props: { user } }; } catch (error) { return { props: { user: null } }; } } -
访问
http://localhost:3000/user/0,页面将显示“用户不存在”。
部署到生产环境
开发完成后,需构建生产版本。
-
停止开发服务器(按
Ctrl + C)。 -
执行构建命令:
npm run build -
启动生产服务器:
npm start -
再次访问页面,行为应与开发模式一致,但性能更优。
关键函数对比表
以下表格总结 Next.js 数据获取方法的核心区别:
| 方法 | 执行时机 | 适用场景 | 是否支持动态路由参数 |
|---|---|---|---|
getServerSideProps |
每次请求时 | 需要实时数据(如用户认证页) | ✅ |
getStaticProps |
构建时(或 ISR) | 内容变化不频繁(如博客文章) | ✅ |
客户端 useEffect |
浏览器加载后 | 无需 SEO 的交互数据 | ❌ |
选择 getServerSideProps 当你需要确保 HTML 在服务端完全生成,例如展示个性化内容或敏感信息(这些不应暴露在客户端初始 HTML 中)。
创建 _app.js 自定义全局布局(可选)
若所有页面共享相同结构(如导航栏),可创建 src/pages/_app.js:
// src/pages/_app.js
export default function MyApp({ Component, pageProps }) {
return (
<div>
<nav>全局导航</nav>
<main>
<Component {...pageProps} />
</main>
</div>
);
}
此后,每个页面组件将自动包裹在此布局内,pageProps 包含从 getServerSideProps 返回的 props。

暂无评论,快来抢沙发吧!