Next.js数据获取入门:`getStaticProps` 与 `getServerSideProps`

Next.js数据获取入门:getStaticPropsgetServerSideProps

作者:码力无边


到目前为止,我们已经构建了一个结构优良、外观精美且导航流畅的应用"外壳"。但一个真正的 Web 应用需要动态的内容来填充这个外壳,这些内容通常来自数据库、API 或内容管理系统 (CMS)。现在,我们正式进入 Next.js 最强大、最核心的领域:数据获取与预渲染

在传统的 React (CSR) 应用中,数据获取通常发生在客户端:组件挂载后,发送一个请求,然后用返回的数据更新状态并重新渲染。这种方式简单,但也带来了 SEO 不佳和初始加载时内容为空白的问题。

Next.js 通过预渲染 (Pre-rendering) 解决了这个问题。它在服务器端提前获取数据,并将数据与组件结合,生成完整的 HTML 页面,然后才发送给客户端。这意味着用户和搜索引擎爬虫第一时间就能看到完整的内容。

Next.js 主要提供了两种预渲染模式,对应着两个核心的数据获取函数:getStaticPropsgetServerSideProps。理解它们的区别,是精通 Next.js 的第一步。

1. getStaticProps:静态站点生成 (SSG)

想象一下你是一位图书管理员。在图书馆开门之前,你就已经把所有书籍(数据)整理好,并分门别类地放在了书架(HTML 页面)上。当读者(用户)进来时,他们可以直接从书架上取走想要的书,速度非常快。

getStaticProps 就是这位图书管理员

核心理念 :它在构建时 (build time) 运行。当你运行 npm run build 命令时,Next.js 会调用所有使用了 getStaticProps 的页面的这个函数,获取数据,然后将每个页面生成为一个静态的 HTML 文件。这些文件可以被部署到 CDN 上,提供极致的访问速度。

何时使用?

当页面的内容可以被提前确定,并且对于所有用户都是相同时,就应该使用 getStaticProps

  • 博客文章
  • 产品列表页
  • 文档网站
  • 营销页面和着陆页

如何实现?

你需要在页面文件(例如 pages/posts.tsx)中 export 一个名为 getStaticPropsasync 函数。

pages/posts.tsx (获取文章列表)

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 一个名为 getServerSidePropsasync 函数。

pages/profile.tsx (获取用户个人信息)

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,敬请期待!

相关推荐
薛定谔的算法6 小时前
JavaScript栈的实现与应用:从基础到实战
前端·javascript·算法
深圳外环高速7 小时前
React 受控组件如何模拟用户输入
前端·react.js
土了个豆子的7 小时前
03.缓存池
开发语言·前端·缓存·visualstudio·c#
手握风云-7 小时前
JavaEE 进阶第四期:开启前端入门之旅(四)
前端
魔云连洲7 小时前
React中的合成事件
前端·javascript·react.js
六月的可乐7 小时前
【干货推荐】AI助理前端UI组件-悬浮球组件
前端·人工智能·ui
呼啦啦呼_7 小时前
Echarts自定义地图显示区域,显示街道学校等区域,对原有区域拆分
前端
浩星7 小时前
iframe引入界面有el-date-picker日期框,点击出现闪退问题处理
前端·vue.js·elementui