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
}
你可以在頂層作用域中導入模組,以在 getStaticProps
中使用。使用的導入將不會被捆綁到用戶端。這表示你可以直接在 getStaticProps
中編寫伺服器端程式碼,包括從你的資料庫抓取資料。
Context 參數
context
參數是一個物件,包含以下鍵
名稱 | 描述 |
---|---|
params | 包含使用動態路由頁面的路由參數。例如,如果頁面名稱為 [id].js ,則 params 看起來會像 { id: ... } 。你應該將此與 getStaticPaths 一起使用,我們稍後會解釋。 |
preview | (已棄用,改用 draftMode )如果頁面處於預覽模式,則 preview 為 true ,否則為 false 。 |
previewData | (已棄用,改用 draftMode )由 setPreviewData 設定的預覽資料集。 |
draftMode | 如果頁面處於草稿模式,則 draftMode 為 true ,否則為 false 。 |
locale | 包含啟用的現用地區設定(如果已啟用)。 |
locales | 包含所有支援的地區設定(如果已啟用)。 |
defaultLocale | 包含已設定的預設地區設定(如果已啟用)。 |
revalidateReason | 提供呼叫函數的原因。可以是以下之一:「build」(在建置時期執行)、「stale」(重新驗證期間已過期,或在開發模式中執行)、「on-demand」(透過隨需重新驗證觸發) |
getStaticProps 回傳值
getStaticProps
函數應回傳一個物件,其中包含 props
、redirect
或 notFound
,後接選用的 revalidate
屬性。
props
props
物件是一個鍵值對,其中每個值都會由頁面組件接收。它應該是一個可序列化的物件,以便可以透過 JSON.stringify
序列化任何傳遞的 props。
export async function getStaticProps(context) {
return {
props: { message: `Next.js is awesome` }, // will be passed to the page component as props
}
}
revalidate
revalidate
屬性是以秒為單位的時間量,超過此時間後可能會發生頁面重新產生(預設為 false
或不重新驗證)。
// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}
深入了解增量靜態再生。
利用 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 }, // will be passed to the page component as 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 }, // will be passed to the page component as 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 will be populated at build time by getStaticProps()
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>
<h3>{post.filename}</h3>
<p>{post.content}</p>
</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() {
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')
// Generally you would parse/transform the contents
// For example you can transform markdown to HTML here
return {
filename,
content: fileContents,
}
})
// By returning { props: { posts } }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts: await Promise.all(posts),
},
}
}
export default Blog
版本歷史記錄
版本 | 變更 |
---|---|
v13.4.0 | App Router 現在已穩定,並簡化了資料抓取 |
v12.2.0 | 隨需增量靜態再生已穩定。 |
v12.1.0 | 新增隨需增量靜態再生(beta 版)。 |
v10.0.0 | 新增 locale 、locales 、defaultLocale 和 notFound 選項。 |
v10.0.0 | 新增 fallback: 'blocking' 回傳選項。 |
v9.5.0 | 穩定的增量靜態再生 |
v9.3.0 | 導入 getStaticProps 。 |
這有幫助嗎?