getServerSideProps

如果您從頁面導出名為 getServerSideProps (伺服器端渲染) 的函數,Next.js 將會在每次請求時使用 getServerSideProps 返回的資料預渲染此頁面。

import type { InferGetServerSidePropsType, GetServerSideProps } from 'next'

type Repo = {
  name: string
  stargazers_count: number
}

export const getServerSideProps = (async (context) => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}) satisfies GetServerSideProps<{
  repo: Repo
}>

export default function Page({
  repo,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
  return repo.stargazers_count
}

請注意,無論渲染類型為何,任何 props 都會傳遞給頁面元件,並且可以在初始 HTML 的客戶端查看。這是為了讓頁面能夠正確地進行水合 (hydrate)。請確保不要在 props 中傳遞任何不應在客戶端可用的敏感資訊。

getServerSideProps 何時執行

getServerSideProps 僅在伺服器端執行,從不在瀏覽器中執行。如果頁面使用了 getServerSideProps,則:

  • 當您直接請求此頁面時,getServerSideProps 會在請求時執行,並且此頁面將使用返回的 props 進行預渲染
  • 當您通過 next/linknext/router 在客戶端頁面轉換中請求此頁面時,Next.js 會向伺服器發送 API 請求,該請求會執行 getServerSideProps

getServerSideProps 返回的 JSON 將用於渲染頁面。所有這些工作都會由 Next.js 自動處理,因此只要您定義了 getServerSideProps,就不需要做任何額外的事情。

您可以使用 next-code-elimination 工具 來驗證 Next.js 從客戶端套件中移除了哪些內容。

getServerSideProps 只能從頁面導出。您不能從非頁面文件中導出它。

請注意,您必須將 getServerSideProps 作為獨立函數導出 — 如果將 getServerSideProps 作為頁面元件的屬性添加,它將無法工作。

getServerSideProps API 參考文件 涵蓋了可以與 getServerSideProps 一起使用的所有參數和 props。

何時應該使用 getServerSideProps

您應該僅在需要渲染其資料必須在請求時獲取的頁面時使用 getServerSideProps。這可能是由於資料的性質或請求的屬性(例如 authorization 標頭或地理位置)。使用 getServerSideProps 的頁面將在請求時進行伺服器端渲染,並且只有在配置了 cache-control 標頭時才會被緩存。

如果您不需要在請求時渲染資料,則應考慮在客戶端 或使用 getStaticProps 獲取資料。

getServerSideProps 或 API 路由

當您想從伺服器獲取資料時,可能會想要使用 API 路由,然後從 getServerSideProps 調用該 API 路由。這是一種不必要且低效的方法,因為它會導致額外的請求,因為 getServerSideProps 和 API 路由都在伺服器上運行。

請看以下示例。API 路由用於從 CMS 獲取一些資料。然後直接從 getServerSideProps 調用該 API 路由。這會產生額外的調用,降低性能。相反,應直接將 API 路由中使用的邏輯導入 getServerSideProps。這可能意味著直接在 getServerSideProps 內部調用 CMS、數據庫或其他 API。

與 Edge API 路由一起使用 getServerSideProps

getServerSideProps 可以與 Serverless 和 Edge 運行時 一起使用,並且您可以在兩者中設置 props。但是,目前在 Edge 運行時中,您無法訪問響應對象。這意味著您無法 — 例如 — 在 getServerSideProps 中添加 cookies。要訪問響應對象,您應繼續使用 Node.js 運行時,這是默認運行時。

您可以通過修改 config 在每個頁面的基礎上明確設置運行時,例如:

pages/index.js
export const config = {
  runtime: 'nodejs', // 或 "edge"
}

export const getServerSideProps = async () => {}

在客戶端獲取資料

如果您的頁面包含頻繁更新的資料,並且您不需要預渲染資料,則可以在客戶端 獲取資料。例如用戶特定的資料:

  • 首先,立即顯示沒有資料的頁面。頁面的某些部分可以使用靜態生成進行預渲染。您可以為缺失的資料顯示加載狀態
  • 然後,在客戶端獲取資料並在準備就緒時顯示

這種方法非常適合用戶儀表板頁面。因為儀表板是一個私有的、用戶特定的頁面,SEO 無關緊要,並且頁面不需要預渲染。資料頻繁更新,這需要在請求時獲取資料。

使用 getServerSideProps 在請求時獲取資料

以下示例顯示如何在請求時獲取資料並預渲染結果。

// 這會在每次請求時調用
export async function getServerSideProps() {
  // 從外部 API 獲取資料
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // 通過 props 將資料傳遞給頁面
  return { props: { data } }
}

export default function Page({ data }) {
  // 渲染資料...
}

使用伺服器端渲染 (SSR) 進行緩存

您可以在 getServerSideProps 中使用緩存標頭 (Cache-Control) 來緩存動態響應。例如,使用 stale-while-revalidate

// 此值在十秒內被視為新鮮 (s-maxage=10)。
// 如果在接下來的 10 秒內重複請求,則之前緩存的值仍將是新鮮的。如果在 59 秒前重複請求,
// 緩存的值將是過時的但仍會渲染 (stale-while-revalidate=59)。
//
// 在後台,將發出重新驗證請求以用新值填充緩存。
// 如果您刷新頁面,您將看到新值。
export async function getServerSideProps({ req, res }) {
  res.setHeader(
    'Cache-Control',
    'public, s-maxage=10, stale-while-revalidate=59'
  )

  return {
    props: {},
  }
}

了解更多關於緩存的資訊。

getServerSideProps 是否會渲染錯誤頁面

如果在 getServerSideProps 中拋出錯誤,它將顯示 pages/500.js 文件。查看 500 頁面 的文件以了解如何創建它。在開發過程中,此文件不會被使用,而是會顯示開發覆蓋層。