Next.js数据获取入门:`getStaticProps` 与 `getServerSideProps`
Next.js数据获取入门:getStaticProps
与 getServerSideProps
作者:码力无边
到目前为止,我们已经构建了一个结构优良、外观精美且导航流畅的应用“外壳”。但一个真正的 Web 应用需要动态的内容来填充这个外壳,这些内容通常来自数据库、API 或内容管理系统 (CMS)。现在,我们正式进入 Next.js 最强大、最核心的领域:数据获取与预渲染。
在传统的 React (CSR) 应用中,数据获取通常发生在客户端:组件挂载后,发送一个请求,然后用返回的数据更新状态并重新渲染。这种方式简单,但也带来了 SEO 不佳和初始加载时内容为空白的问题。
Next.js 通过预渲染 (Pre-rendering) 解决了这个问题。它在服务器端提前获取数据,并将数据与组件结合,生成完整的 HTML 页面,然后才发送给客户端。这意味着用户和搜索引擎爬虫第一时间就能看到完整的内容。
Next.js 主要提供了两种预渲染模式,对应着两个核心的数据获取函数:getStaticProps
和 getServerSideProps
。理解它们的区别,是精通 Next.js 的第一步。
1. getStaticProps
:静态站点生成 (SSG)
想象一下你是一位图书管理员。在图书馆开门之前,你就已经把所有书籍(数据)整理好,并分门别类地放在了书架(HTML 页面)上。当读者(用户)进来时,他们可以直接从书架上取走想要的书,速度非常快。
getStaticProps
就是这位图书管理员。
核心理念:它在构建时 (build time) 运行。当你运行 npm run build
命令时,Next.js 会调用所有使用了 getStaticProps
的页面的这个函数,获取数据,然后将每个页面生成为一个静态的 HTML 文件。这些文件可以被部署到 CDN 上,提供极致的访问速度。
何时使用?
当页面的内容可以被提前确定,并且对于所有用户都是相同时,就应该使用 getStaticProps
。
- 博客文章
- 产品列表页
- 文档网站
- 营销页面和着陆页
如何实现?
你需要在页面文件(例如 pages/posts.tsx
)中 export
一个名为 getStaticProps
的 async
函数。
pages/posts.tsx
(获取文章列表)
import type { GetStaticProps, InferGetStaticPropsType } from 'next';
import Link from 'next/link';// 定义文章的数据类型
type Post = {id: number;title: string;
};// 1. 定义 getStaticProps 函数
export const getStaticProps: GetStaticProps<{ posts: Post[] }> = async () => {// 在实际应用中,这里会 fetch 一个外部 API// const res = await fetch('https://api.example.com/posts');// const posts: Post[] = await res.json();// 为了演示,我们使用模拟数据const posts: Post[] = [{ id: 1, title: '你好,Next.js' },{ id: 2, title: '深入理解路由' },];// 函数必须返回一个带有 props 属性的对象// 这个 props 对象会作为属性传递给页面组件return {props: {posts,},};
};// 2. 页面组件通过 props 接收数据
function PostsPage({ posts }: InferGetStaticPropsType<typeof getStaticProps>) {return (<div><h1>文章列表</h1><ul>{posts.map((post) => (<li key={post.id}><Link href={`/posts/${post.id}`}><a>{post.title}</a></Link></li>))}</ul></div>);
}export default PostsPage;
代码解读:
getStaticProps
在服务器端运行,所以你可以在这里直接访问数据库或使用私有 API 密钥,它们不会暴露给客户端。InferGetStaticPropsType
是一个非常有用的 TypeScript 工具类型,它可以自动推断出getStaticProps
返回的props
的类型,让你的页面组件获得类型安全。
2. getServerSideProps
:服务器端渲染 (SSR)
现在,想象你是一位新闻直播记者。当有突发事件(用户请求)发生时,你立刻赶到现场,获取最新的信息(实时数据),然后进行现场直播(生成 HTML 页面)。你的报道总是最新的,但每次都需要一个反应时间。
getServerSideProps
就是这位新闻记者。
核心理念:它在每次请求时 (request time) 运行。当用户访问一个使用了 getServerSideProps
的页面时,服务器会先执行这个函数,获取最新的数据,然后实时地将数据和组件渲染成 HTML,再发送给用户。
何时使用?
当页面的内容必须在每次请求时都保持最新,或者内容是根据用户身份等请求信息动态生成的。
- 用户个人中心、仪表盘
- 需要登录才能访问的页面
- 实时性要求极高的数据展示(如股票行情、购物车)
如何实现?
与 getStaticProps
类似,你需要在页面文件中 export
一个名为 getServerSideProps
的 async
函数。
pages/profile.tsx
(获取用户个人信息)
import type { GetServerSideProps, InferGetServerSidePropsType } from 'next';type UserProfile = {name: string;email: string;lastLogin: string;
};// 1. 定义 getServerSideProps 函数
// 它接收一个 context 对象,里面包含请求信息
export const getServerSideProps: GetServerSideProps<{ profile: UserProfile }> = async (context) => {// 你可以从 context.req 中获取 cookies, headers 等信息// const userId = context.req.cookies.userId;// 模拟从 API 获取用户数据const profile: UserProfile = {name: '码力无边',email: 'user@example.com',lastLogin: new Date().toISOString(), // 每次访问都是最新的时间};return {props: {profile,},};
};// 2. 页面组件通过 props 接收数据
function ProfilePage({ profile }: InferGetServerSidePropsType<typeof getServerSideProps>) {return (<div><h1>个人中心</h1><p>姓名:{profile.name}</p><p>邮箱:{profile.email}</p><p>上次登录时间:{profile.lastLogin}</p></div>);
}export default ProfilePage;
对比总结:我该如何选择?
特性 | getStaticProps (SSG) | getServerSideProps (SSR) |
---|---|---|
运行时间 | 构建时 (Build Time) | 每次请求时 (Request Time) |
性能 | 极快 (从 CDN 直接提供静态文件) | 较快 (但比 SSG 慢,需要服务器计算) |
数据新鲜度 | 构建时的快照,可能过时 | 永远是最新鲜的数据 |
SEO | 极佳 (HTML 内容完整) | 极佳 (HTML 内容完整) |
适用场景 | 博客、文档、营销页、产品列表 | 用户仪表盘、需登录页面、实时数据 |
可部署性 | 可部署在任何静态主机上 | 需要 Node.js 服务器环境 |
一个黄金法则
Next.js 官方给出了一个非常明确的建议,可以作为你的黄金法则:
“如果可以,请优先使用
getStaticProps
。”
一个静态生成的页面总是比动态渲染的页面更快。你应该努力将你的网站尽可能地静态化。即使数据会更新,Next.js 也提供了增量静态再生 (ISR) 这样的高级技术(我们后续会讲)来更新静态内容。只有当页面内容必须在用户请求的那一刻才能确定时,才使用 getServerSideProps
。
总结
今天,我们打开了 Next.js 数据获取的大门,学习了两种最核心的预渲染数据获取方式。
getStaticProps
(图书管理员):构建时运行,生成静态 HTML,性能极致,适用于内容不频繁变动的页面。getServerSideProps
(新闻记者):请求时运行,实时渲染 HTML,保证数据最新,适用于高度动态和个性化的页面。
理解并根据场景正确选用这两种方法,是构建高性能 Next.js 应用的关键。在接下来的文章中,我们将分别深入这两种模式,探讨它们的更多细节,例如如何结合动态路由使用 getStaticProps
,敬请期待!