Next.js Server Components fetch 資料抓取與快取
在 App Router 中,資料擷取(Data Fetching)變得非常直觀。你不再需要依賴舊版的 getStaticProps 或 getServerSideProps,而是可以直接在 伺服器元件 (Server Components) 中使用簡單的 async/await。
在 Server Components 中擷取數據
這是 Next.js 推薦的標準做法。因為組件在伺服器端執行,你可以直接存取資料庫或內部的 API,且擷取的過程不會影響用戶端的 Bundle Size。
// app/blog/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 Page() {
const posts = await getPosts();
return (
<main>
<h1>部落格文章</h1>
{posts.map((post) => (
<article key={post.id}>{post.title}</article>
))}
</main>
);
}
快取機制 (Caching)
Next.js 擴充了 Web 原生的 fetch API,為其增加了強大的快取功能。
預設快取
預設情況下,fetch 的結果會被自動快取(這相當於舊版的靜態網站生成)。
資料更新頻率 (Revalidation)
如果你希望資料每隔一段時間更新,可以設定 next.revalidate:
fetch('https://...', { next: { revalidate: 3600 } }); // 每小時重新驗證一次
強制不快取 (Dynamic Fetching)
如果你需要每一秒都獲取最新數據(例如股市跳動),可以設定 cache: 'no-store':
fetch('https://...', { cache: 'no-store' });
請求記憶化 (Request Memoization)
如果你在同一個渲染樹(同一個路徑下)的不同元件中多次呼叫相同的 fetch 請求,Next.js 會自動合併它們,只發送一次請求到來源 API。
這意味著你不需要手動將資料從父組件傳遞到子組件,各個組件可以「各取所需」。
// layout.tsx 中呼叫了 getUser
// page.tsx 中也呼叫了 getUser
// Next.js 只會向伺服器發送一次 getUser 請求
直接讀取後端資源
如果你的資料庫就在伺服器端,你甚至不需要透過 API 中轉,直接使用 ORM(如 Prisma, Drizzle)或原生 Query:
import db from '@/lib/db';
async function getUsers() {
return await db.user.findMany(); // 直接讀取資料庫,超快!
}
小結
- 簡約:直接在元件寫
async/await。 - 快取:善用
fetch的選項來平衡效能與即時性。 - 安全:敏感的資料處理邏輯永遠留在伺服器端。