Next.js 数据获取:方法与实践指南

1. 引言

Next.js 提供了灵活的数据获取机制,支持静态生成(SSG)、服务器端渲染(SSR)和客户端渲染(CSR),适用于不同场景。数据获取是 Next.js 应用的核心,直接影响页面加载速度、SEO 和用户体验。本文将全面探讨 Pages Router 和 App Router(13.x+)中的数据获取方法,提供实现示例和优化建议。


2. Next.js 数据获取概述

2.1 数据获取的核心概念

  • SSG(Static Site Generation):构建时生成静态页面,适合内容稳定的场景。
  • SSR(Server-Side Rendering):请求时动态渲染,适合实时数据。
  • CSR(Client-Side Rendering):客户端获取数据,适合交互式页面。
  • 混合模式:结合多种方法优化性能。

2.2 App Router 与 Pages Router 的区别

  • Pages Router:依赖特定函数(如 getStaticProps)。
  • App Router:更灵活,支持服务器组件直接获取数据,减少专用函数依赖。
  • 参考:Next.js 数据获取文档。

3. Pages Router 中的数据获取方法

3.1 getStaticProps

  • 用途:构建时获取数据,生成静态页面。
  • 实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

// pages/index.js

export async function getStaticProps() {

  const res = await fetch("https://jsonplaceholder.typicode.com/posts");

  const posts = await res.json();

  return {

    props: { posts }, // 传递给页面组件

    revalidate: 10, // 每 10 秒重新验证(ISR)

  };

}

export default function Home({ posts }) {

  return (

    

          {posts.map((post) => (

            

  • {post.title}
  •       ))}

        

  );

}

  • 场景:博客、文档页面。

3.2 getServerSideProps

  • 用途:请求时获取数据,动态渲染。
  • 实现

1

2

3

4

5

6

7

8

9

// pages/post/[id].js

export async function getServerSideProps({ params }) {

  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);

  const post = await res.json();

  return { props: { post } };

}

export default function Post({ post }) {

  return

{post.title}

;

}

  • 场景:实时仪表盘、用户个性化页面。

3.3 getInitialProps

  • 用途:早期方法,同时支持 SSR 和 CSR(现已不推荐)。
  • 实现

1

2

3

4

5

6

7

8

9

// pages/index.js

Home.getInitialProps = async () => {

  const res = await fetch("https://jsonplaceholder.typicode.com/posts");

  const posts = await res.json();

  return { posts };

};

export default function Home({ posts }) {

  return

    {posts.map((p) =>
  • {p.title}
  • )}
;

}

  • 注意:优先使用 getStaticProps 或 getServerSideProps

4. App Router 中的数据获取方法

4.1 服务器组件中的直接获取

  • 用途:服务器组件默认支持异步数据获取,无需专用函数。
  • 实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

// app/page.jsx

async function fetchPosts() {

  const res = await fetch("https://jsonplaceholder.typicode.com/posts");

  return res.json();

}

export default async function Home() {

  const posts = await fetchPosts();

  return (

    

          {posts.map((post) => (

            

  • {post.title}
  •       ))}

        

  );

}

  • 优点:简洁,减少样板代码。

4.2 客户端组件中的 Fetch

  • 用途:动态数据获取,使用 React Hooks。
  • 实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

// components/PostList.jsx

"use client";

import { useState, useEffect } from "react";

export default function PostList() {

  const [posts, setPosts] = useState([]);

  useEffect(() => {

    fetch("https://jsonplaceholder.typicode.com/posts")

      .then((res) => res.json())

      .then((data) => setPosts(data));

  }, []);

  return (

    

          {posts.map((post) => (

            

  • {post.title}
  •       ))}

        

  );

}

  • 场景:交互式 UI。

4.3 使用 Suspense 和 Loading

  • 用途:处理异步加载状态。
  • 实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// app/page.jsx

import { Suspense } from "react";

async function Posts() {

  const res = await fetch("https://jsonplaceholder.typicode.com/posts");

  const posts = await res.json();

  return

    {posts.map((p) =>
  • {p.title}
  • )}
;

}

export default function Home() {

  return (

    Loading...

}>

      

    

  );

}

  • 全局 Loading

1

2

3

4

// app/loading.jsx

export default function Loading() {

  return

Loading...
;

}


5. 数据获取的高级应用

5.1 动态路由与参数

  • App Router

1

2

3

4

5

// app/posts/[id]/page.jsx

export default async function Post({ params }) {

  const post = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`).then((res) => res.json());

  return

{post.title}

;

}

5.2 API 路由与数据获取

  • 实现

1

2

3

4

5

6

// app/api/posts/route.js

import { NextResponse } from "next/server";

export async function GET() {

  const posts = await fetch("https://jsonplaceholder.typicode.com/posts").then((res) => res.json());

  return NextResponse.json(posts);

}

  • 调用:参见客户端组件。

5.3 缓存与重新验证

  • 缓存

1

await fetch("https://api.example.com/data", { cache: "force-cache" }); // 默认缓存

  • 重新验证

1

await fetch("https://api.example.com/data", { next: { revalidate: 3600 } }); // 每小时更新


6. 最佳实践与优化

6.1 性能优化

  • 优先 SSG:内容稳定时使用 getStaticProps 或服务器组件。
  • 延迟加载:结合  和 dynamic 导入。
  • 参考:Next.js 优化指南。

6.2 错误处理与调试

  • 错误页面

1

2

3

4

5

6

7

8

9

10

// app/error.jsx

"use client";

export default function Error({ error, reset }) {

  return (

    

      

Error: {error.message}

      

    

  );

}

  • 调试:用 Chrome DevTools 检查网络请求。

6.3 推荐资源与工具

  • Next.js 数据获取文档。
  • Vercel 示例。
  • React Query(客户端数据管理)。

7. 结论

Next.js 的数据获取机制为开发者提供了从静态到动态的多种选择。Pages Router 的专用函数适合传统项目,而 App Router 的服务器组件和灵活性代表未来趋势。通过合理选择方法并优化性能,可以构建高效的 Web 应用。下一节可探讨具体案例(如电商数据获取),请告诉我你的兴趣!(资料来源:52kanjuqing)

你可能感兴趣的:(javascript,前端,数据库)