getStaticProps
如果你從頁面中匯出名為 getStaticProps
的函式(靜態網站生成),Next.js 將會在建置時使用 getStaticProps
回傳的 props 預先渲染這個頁面。
import type { InferGetStaticPropsType, GetStaticProps } from 'next'
type Repo = {
name: string
stargazers_count: number
}
export const getStaticProps = (async (context) => {
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const repo = await res.json()
return { props: { repo } }
}) satisfies GetStaticProps<{
repo: Repo
}>
export default function Page({
repo,
}: InferGetStaticPropsType<typeof getStaticProps>) {
return repo.stargazers_count
}
export async function getStaticProps() {
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const repo = await res.json()
return { props: { repo } }
}
export default function Page({ repo }) {
return repo.stargazers_count
}
請注意,無論渲染類型為何,任何
props
都會傳遞給頁面元件,並且可以在初始 HTML 中於客戶端查看。這是為了讓頁面能夠正確地水合 (hydrate)。請確保不要在props
中傳遞任何不應在客戶端顯示的敏感資訊。
getStaticProps
API 參考文件涵蓋了所有可以與 getStaticProps
一起使用的參數和 props。
何時應該使用 getStaticProps?
在以下情況下,你應該使用 getStaticProps
:
- 渲染頁面所需的資料在使用者請求之前就已於建置時準備好
- 資料來自無頭 CMS (headless CMS)
- 頁面必須預先渲染(為了 SEO)並且速度要非常快 —
getStaticProps
會生成HTML
和JSON
檔案,兩者都可以透過 CDN 快取以提升效能 - 資料可以公開快取(非使用者特定)。在某些特定情況下,可以透過使用中介軟體 (Middleware) 重寫路徑來繞過此條件。
getStaticProps 何時執行
getStaticProps
永遠在伺服器端執行,不會在客戶端執行。你可以使用這個工具驗證 getStaticProps
中的程式碼是否已從客戶端套件中移除。
getStaticProps
總是在next build
期間執行- 使用
fallback: true
時,getStaticProps
會在背景執行 - 使用
fallback: blocking
時,getStaticProps
會在初始渲染前呼叫 - 使用
revalidate
時,getStaticProps
會在背景執行 - 使用
revalidate()
時,getStaticProps
會根據需求在背景執行
當與增量靜態再生 (Incremental Static Regeneration) 結合使用時,getStaticProps
會在過時頁面重新驗證期間於背景執行,並將新頁面提供給瀏覽器。
由於 getStaticProps
生成的是靜態 HTML,因此無法存取傳入的請求(例如查詢參數或 HTTP 標頭)。如果你的頁面需要存取請求,可以考慮在使用 getStaticProps
的同時搭配使用中介軟體 (Middleware)。
使用 getStaticProps 從 CMS 獲取資料
以下範例展示如何從 CMS 獲取部落格文章列表。
// posts 將由 getStaticProps() 在建置時填充
export default function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
// 此函式會在伺服器端的建置時呼叫
// 不會在客戶端呼叫,因此甚至可以
// 直接執行資料庫查詢
export async function getStaticProps() {
// 呼叫外部 API 端點以獲取文章
// 可以使用任何資料獲取函式庫
const res = await fetch('https://.../posts')
const posts = await res.json()
// 透過回傳 { props: { posts } },Blog 元件
// 將在建置時收到 `posts` 作為 prop
return {
props: {
posts,
},
}
}
// posts 將由 getStaticProps() 在建置時填充
export default function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
// 此函式會在伺服器端的建置時呼叫
// 不會在客戶端呼叫,因此甚至可以
// 直接執行資料庫查詢
export async function getStaticProps() {
// 呼叫外部 API 端點以獲取文章
// 可以使用任何資料獲取函式庫
const res = await fetch('https://.../posts')
const posts = await res.json()
// 透過回傳 { props: { posts } },Blog 元件
// 將在建置時收到 `posts` 作為 prop
return {
props: {
posts,
},
}
}
getStaticProps
API 參考文件涵蓋了所有可以與 getStaticProps
一起使用的參數和 props。
直接撰寫伺服器端程式碼
由於 getStaticProps
僅在伺服器端執行,因此永遠不會在客戶端執行。它甚至不會包含在瀏覽器的 JS 套件中,因此你可以直接撰寫資料庫查詢而不必擔心它們會被傳送到瀏覽器。
這意味著,與其從 getStaticProps
中呼叫一個API 路由(該路由本身從外部來源獲取資料),不如直接在 getStaticProps
中撰寫伺服器端程式碼。
以下面的範例為例。一個 API 路由用於從 CMS 獲取一些資料,然後該 API 路由直接從 getStaticProps
中呼叫。這樣會產生額外的呼叫,降低效能。相反,可以透過使用 lib/
目錄來共享從 CMS 獲取資料的邏輯,然後與 getStaticProps
共享。
// 以下函式與 getStaticProps 和 API 路由
// 共享,位於 `lib/` 目錄中
export async function loadPosts() {
// 呼叫外部 API 端點以獲取文章
const res = await fetch('https://.../posts/')
const data = await res.json()
return data
}
// pages/blog.js
import { loadPosts } from '../lib/load-posts'
// 此函式僅在伺服器端執行
export async function getStaticProps() {
// 與其獲取 `/api` 路由,不如直接
// 在 `getStaticProps` 中呼叫相同的函式
const posts = await loadPosts()
// 回傳的 props 將傳遞給頁面元件
return { props: { posts } }
}
或者,如果你沒有使用 API 路由來獲取資料,那麼可以直接在 getStaticProps
中使用 fetch()
API 來獲取資料。
要驗證 Next.js 從客戶端套件中移除了哪些內容,可以使用 next-code-elimination 工具。
靜態生成 HTML 和 JSON
當使用 getStaticProps
的頁面在建置時預先渲染時,除了頁面的 HTML 檔案外,Next.js 還會生成一個包含 getStaticProps
執行結果的 JSON 檔案。
這個 JSON 檔案將透過 next/link
或 next/router
用於客戶端路由。當你導航到使用 getStaticProps
預先渲染的頁面時,Next.js 會獲取這個 JSON 檔案(在建置時預先計算)並將其用作頁面元件的 props。這意味著客戶端頁面轉換不會呼叫 getStaticProps
,因為只會使用匯出的 JSON。
當使用增量靜態生成時,getStaticProps
會在背景執行以生成客戶端導航所需的 JSON。你可能會看到對同一頁面發出的多個請求,但這是預期的行為,不會影響終端使用者的效能。
可以在哪裡使用 getStaticProps
getStaticProps
只能從頁面中匯出。你不能從非頁面檔案、_app
、_document
或 _error
中匯出它。
這個限制的原因之一是 React 需要在頁面渲染之前擁有所有必要的資料。
此外,你必須將 getStaticProps
作為獨立函式匯出 — 如果你將 getStaticProps
作為頁面元件的屬性添加,它將無法工作。
須知:如果你建立了自訂應用程式,請確保按照連結文件中的說明將
pageProps
傳遞給頁面元件,否則 props 將為空。
在開發模式下每次請求都會執行
在開發模式 (next dev
) 下,getStaticProps
會在每次請求時呼叫。
預覽模式
你可以使用預覽模式 (Preview Mode) 暫時繞過靜態生成,並在請求時而非建置時渲染頁面。例如,你可能正在使用無頭 CMS 並希望在草稿發布前預覽它們。