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
}
請注意,無論渲染類型為何,任何
props
都會傳遞到頁面元件,並且可以在用戶端初始 HTML 中檢視。這是為了讓頁面能夠正確地 hydration。請確保您不要在props
中傳遞任何不應在用戶端上提供的敏感資訊。
getStaticProps
API 參考涵蓋了可以與 getStaticProps
一起使用的所有參數和 props。
何時應該使用 getStaticProps?
如果符合以下情況,您應該使用 getStaticProps
:
- 渲染頁面所需的資料在使用者請求之前於建置時期可用
- 資料來自 headless CMS
- 頁面必須預先渲染 (為了 SEO) 並且速度非常快 —
getStaticProps
產生HTML
和JSON
檔案,兩者都可以由 CDN 快取以提高效能 - 資料可以公開快取 (非使用者特定)。在某些特定情況下,可以使用中介軟體來重寫路徑以繞過此條件。
getStaticProps 何時執行
getStaticProps
始終在伺服器上執行,絕不在用戶端上執行。您可以使用此工具驗證在 getStaticProps
內部撰寫的程式碼已從用戶端捆綁包中移除。
getStaticProps
始終在next build
期間執行- 使用
fallback: true
時,getStaticProps
在背景執行 - 使用
fallback: blocking
時,getStaticProps
在初始渲染之前呼叫 - 使用
revalidate
時,getStaticProps
在背景執行 - 使用
revalidate()
時,getStaticProps
在背景按需執行
當與遞增靜態再生結合使用時,getStaticProps
將在背景執行,同時重新驗證陳舊頁面,並將最新頁面提供給瀏覽器。
getStaticProps
無法存取傳入的請求 (例如查詢參數或 HTTP 標頭),因為它產生靜態 HTML。如果您需要存取頁面的請求,請考慮除了 getStaticProps
之外,還使用中介軟體。
使用 getStaticProps 從 CMS 抓取資料
以下範例示範如何從 CMS 抓取部落格文章列表。
// posts will be populated at build time by getStaticProps()
export default function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export async function getStaticProps() {
// Call an external API endpoint to get posts.
// You can use any data fetching library
const res = await fetch('https://.../posts')
const posts = await res.json()
// By returning { props: { posts } }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts,
},
}
}
getStaticProps
API 參考涵蓋了可以與 getStaticProps
一起使用的所有參數和 props。
直接撰寫伺服器端程式碼
由於 getStaticProps
僅在伺服器端執行,因此絕不會在用戶端端執行。它甚至不會包含在瀏覽器的 JS 捆綁包中,因此您可以直接撰寫資料庫查詢,而不會將其傳送到瀏覽器。
這表示您可以直接在 getStaticProps
中撰寫伺服器端程式碼,而不是從 getStaticProps
抓取API 路由 (其本身從外部來源抓取資料)。
以下列範例為例。API 路由用於從 CMS 抓取一些資料。然後直接從 getStaticProps
呼叫該 API 路由。這會產生額外的呼叫,降低效能。相反地,可以使用 lib/
目錄來共用從 CMS 抓取資料的邏輯。然後可以與 getStaticProps
共用。
// The following function is shared
// with getStaticProps and API routes
// from a `lib/` directory
export async function loadPosts() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts/')
const data = await res.json()
return data
}
// pages/blog.js
import { loadPosts } from '../lib/load-posts'
// This function runs only on the server side
export async function getStaticProps() {
// Instead of fetching your `/api` route you can call the same
// function directly in `getStaticProps`
const posts = await loadPosts()
// Props returned will be passed to the page component
return { props: { posts } }
}
或者,如果您沒有使用 API 路由來抓取資料,則可以在 getStaticProps
中直接使用 fetch()
API 來抓取資料。
若要驗證 Next.js 從用戶端捆綁包中移除的內容,您可以使用 next-code-elimination 工具。
靜態產生 HTML 和 JSON
當在建置時期預先渲染具有 getStaticProps
的頁面時,除了頁面 HTML 檔案外,Next.js 還會產生一個 JSON 檔案,其中包含執行 getStaticProps
的結果。
此 JSON 檔案將用於透過 next/link
或 next/router
的用戶端路由。當您導航到使用 getStaticProps
預先渲染的頁面時,Next.js 會抓取此 JSON 檔案 (在建置時期預先計算),並將其用作頁面元件的 props。這表示用戶端頁面轉換將不會呼叫 getStaticProps
,因為僅使用匯出的 JSON。
當使用遞增靜態產生時,getStaticProps
將在背景執行,以產生用戶端導航所需的 JSON。您可能會看到針對同一頁面發出多個請求,但這是預期的,並且對終端使用者效能沒有影響。
何處可以使用 getStaticProps
getStaticProps
只能從頁面匯出。您不能從非頁面檔案、_app
、_document
或 _error
匯出它。
此限制的原因之一是 React 需要在渲染頁面之前擁有所有必需的資料。
此外,您必須將 getStaticProps
作為獨立函式匯出 — 如果您將 getStaticProps
新增為頁面元件的屬性,則無法運作。
要知道的好事:如果您已建立自訂 app,請確保您將
pageProps
傳遞到頁面元件,如連結的文件所示,否則 props 將為空。
在開發環境中,每次請求都會執行
在開發環境 (next dev
) 中,getStaticProps
將在每次請求時呼叫。
預覽模式
您可以使用預覽模式暫時繞過靜態產生,並在請求時而不是建置時渲染頁面。例如,您可能正在使用 headless CMS,並希望在發佈草稿之前預覽它們。
這有幫助嗎?