跳轉至

建立 2026-09-16 更新 2026-09-16

資料抓取

因為 Server Component 本來就只在伺服器端執行,抓資料不需要 useEffect 或額外的資料層套件,直接把元件宣告成 async 函式、用 await 抓資料即可。

基本寫法

app/posts/page.tsx
async function getPosts() {
  const res = await fetch("https://api.example.com/posts");
  if (!res.ok) throw new Error("無法取得文章列表");
  return res.json();
}

export default async function PostsPage() {
  const posts = await getPosts();

  return (
    <ul>
      {posts.map((post: { id: string; title: string }) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

Next.js 擴充了原生 fetch,加上快取與重新驗證選項;細節見 快取與重新驗證。資料庫查詢(例如用 Prisma)也可以直接寫在 Server Component 裡,原理相同。

並行抓取 vs. 循序抓取

多個資料來源互不相依時,先各自建立 Promise、再一起 await,可以平行進行、縮短總等待時間:

async function getUser(id: string) { /* ... */ }
async function getPosts(id: string) { /* ... */ }

export default async function ProfilePage({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;

  // 兩個請求同時發出,而不是一個等完才發下一個
  const userPromise = getUser(id);
  const postsPromise = getPosts(id);
  const [user, posts] = await Promise.all([userPromise, postsPromise]);

  return (
    <>
      <h1>{user.name}</h1>
      <PostList posts={posts} />
    </>
  );
}

若後一個請求的參數依賴前一個請求的結果,才需要循序 await;否則預設應該讓互不相依的請求並行。

用 loading.tsx 搭配 Suspense 做串流

資料抓取需要時間時,在同一路由層級加上 loading.tsx,Next.js 會自動用 React Suspense 包住該路由,先顯示載入畫面、資料就緒後再換成實際內容,使用者不會看到整頁空白:

app/posts/loading.tsx
export default function Loading() {
  return <p>文章載入中</p>;
}

想要更精細地控制(例如頁面裡只有某個區塊要顯示載入中,其餘部分先顯示),可以直接用 <Suspense> 包住個別的 async 元件。

推薦影音

在 Server Components 抓資料

簡述:Codevolution 這支影片示範如何在 Server Component 裡呼叫 API、處理 loading 與錯誤狀態,內容與上面範例的寫法一致,適合想看實際操作過程的學習者。

下一步

資料抓到之後,Next.js 還會依快取設定決定這個結果能不能重複使用、要不要定期更新,詳見 快取與重新驗證