getStaticProps
匯出一個名為 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
}
您可以在頂層作用域匯入模組供 getStaticProps
使用。這些匯入的模組不會被打包到客戶端。這意味著您可以直接在 getStaticProps
中撰寫伺服器端程式碼,包括從資料庫獲取資料。
Context 參數
context
參數是一個包含以下鍵值的物件:
名稱 | 說明 |
---|---|
params | 包含使用動態路由頁面的路由參數。例如,如果頁面名稱是 [id].js ,則 params 會像 { id: ... } 。您應該與 getStaticPaths 一起使用此參數,我們稍後會說明。 |
preview | (已棄用,改用 draftMode ) 如果頁面處於預覽模式 (Preview Mode),則 preview 為 true ,否則為 false 。 |
previewData | (已棄用,改用 draftMode ) 由 setPreviewData 設定的預覽 (preview) 資料。 |
draftMode | 如果頁面處於草稿模式 (Draft Mode),則 draftMode 為 true ,否則為 false 。 |
locale | 包含當前啟用的語言環境 (若已啟用)。 |
locales | 包含所有支援的語言環境 (若已啟用)。 |
defaultLocale | 包含設定的預設語言環境 (若已啟用)。 |
revalidateReason | 提供函式被呼叫的原因。可能的值為:"build" (在建置時執行)、"stale" (重新驗證週期已過期,或在開發模式 (development mode) 下執行)、"on-demand" (透過隨需重新驗證 (on-demand revalidation) 觸發) |
getStaticProps 回傳值
getStaticProps
函式應回傳一個包含 props
、redirect
或 notFound
的物件,後者可選擇性地包含 revalidate
屬性。
props
props
物件是一個鍵值對,其中每個值都會傳遞給頁面元件。它應該是一個可序列化物件 (serializable object),以便任何傳遞的 props 都可以使用 JSON.stringify
序列化。
export async function getStaticProps(context) {
return {
props: { message: `Next.js is awesome` }, // 將作為 props 傳遞給頁面元件
}
}
revalidate
revalidate
屬性是頁面可以重新生成的秒數 (預設為 false
或無重新驗證)。
// 此函式會在伺服器端的建置階段被呼叫。
// 如果啟用重新驗證且收到新請求,可能會在無伺服器函式上再次呼叫
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js 會嘗試重新生成頁面:
// - 當收到請求時
// - 最多每 10 秒一次
revalidate: 10, // 單位為秒
}
}
了解更多關於增量靜態再生 (Incremental Static Regeneration)。
利用 ISR 的頁面快取狀態可以透過讀取 x-nextjs-cache
回應標頭的值來判斷。可能的值如下:
MISS
- 路徑不在快取中 (最多發生一次,在首次訪問時)STALE
- 路徑在快取中但已超過重新驗證時間,因此會在背景更新HIT
- 路徑在快取中且未超過重新驗證時間
notFound
notFound
布林值允許頁面回傳 404
狀態和 404 頁面。當 notFound: true
時,即使之前已成功生成頁面,頁面也會回傳 404
。這用於支援像使用者生成內容被作者刪除等使用情境。請注意,notFound
遵循與此處描述相同的 revalidate
行為。
export async function getStaticProps(context) {
const res = await fetch(`https://.../data`)
const data = await res.json()
if (!data) {
return {
notFound: true,
}
}
return {
props: { data }, // 將作為 props 傳遞給頁面元件
}
}
須知:對於
fallback: false
模式,不需要使用notFound
,因為只有從getStaticPaths
回傳的路徑會被預先渲染。
redirect
redirect
物件允許重新導向到內部或外部資源。它應符合 { destination: string, permanent: boolean }
的結構。
在極少數情況下,您可能需要為舊版 HTTP
用戶端指定自訂狀態碼以正確重新導向。在這些情況下,您可以使用 statusCode
屬性代替 permanent
屬性,但不能同時使用兩者。您也可以設定 basePath: false
,類似於 next.config.js
中的重新導向。
export async function getStaticProps(context) {
const res = await fetch(`https://...`)
const data = await res.json()
if (!data) {
return {
redirect: {
destination: '/',
permanent: false,
// statusCode: 301
},
}
}
return {
props: { data }, // 將作為 props 傳遞給頁面元件
}
}
如果重新導向在建置時已知,應改為在 next.config.js
中新增。
讀取檔案:使用 process.cwd()
可以在 getStaticProps
中直接從檔案系統讀取檔案。
為此,您需要取得檔案的完整路徑。
由於 Next.js 將您的程式碼編譯到單獨的目錄中,您不能使用 __dirname
,因為它回傳的路徑會與 Pages Router 不同。
相反,您可以使用 process.cwd()
,它會提供 Next.js 正在執行的目錄。
import { promises as fs } from 'fs'
import path from 'path'
// posts 將在建置時由 getStaticProps() 填充
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>
<h3>{post.filename}</h3>
<p>{post.content}</p>
</li>
))}
</ul>
)
}
// 此函式會在伺服器端的建置階段被呼叫。
// 不會在客戶端呼叫,因此您甚至可以
// 直接進行資料庫查詢。
export async function getStaticProps() {
const postsDirectory = path.join(process.cwd(), 'posts')
const filenames = await fs.readdir(postsDirectory)
const posts = filenames.map(async (filename) => {
const filePath = path.join(postsDirectory, filename)
const fileContents = await fs.readFile(filePath, 'utf8')
// 通常您會在此解析/轉換內容
// 例如可以將 markdown 轉換為 HTML
return {
filename,
content: fileContents,
}
})
// 透過回傳 { props: { posts } },Blog 元件
// 將在建置時接收 `posts` 作為 prop
return {
props: {
posts: await Promise.all(posts),
},
}
}
export default Blog
版本歷史
版本 | 變更 |
---|---|
v13.4.0 | App Router 現已穩定,並簡化了資料獲取 |
v12.2.0 | 隨需增量靜態再生 (On-Demand Incremental Static Regeneration) 穩定化。 |
v12.1.0 | 新增 隨需增量靜態再生 (On-Demand Incremental Static Regeneration) (beta)。 |
v10.0.0 | 新增 locale 、locales 、defaultLocale 和 notFound 選項。 |
v10.0.0 | 新增 fallback: 'blocking' 回傳選項。 |
v9.5.0 | 穩定化 增量靜態再生 (Incremental Static Regeneration) |
v9.3.0 | 引入 getStaticProps 。 |