getStaticProps

如果你在一個頁面裡輸出了 getStaticProps 函式(靜態網頁生成),Next.js 將會在建置期間(build time)時透過 getStaticProps 回傳的 props 來預先渲染該頁面。

export async function getStaticProps(context) { return { props: {} // 會被當作 props 傳入頁面元件中 } }

注意不管是哪一種渲染類型,所有 props 的內容都會被傳入頁面元件中,且客戶端能透過 HTML 查閱。這是為了確保頁面能夠正確的注入(hydrated)內容。請確保你沒有把任何不應該出現在客戶端的敏感資訊放在 props 中。

什麼時候該使用 getStaticProps?

如果你符合下面的情況,你應該用 getStaticProps:

  • 渲染頁面時的資料必須在建置期間時取得(在使用者發出請求以前)
  • 資料是透過無頭內容管理系統(Headless CMS)取得
  • 頁面必須預先渲染(考慮到 SEO)且載入迅速-getStaticProps 生成的 HTMLJSON 檔案能夠被快取成 CDN 提升效能
  • 資料能夠被公開快取(也就是不屬於特定使用者)。在某些特殊情況下你可以透過中間件(Middleware)重寫路徑的方式來達成這個條件

getStaticProps 什麼時候執行?

getStaticProps 只會在伺服端執行而不是客戶端。你可以用 這個工具 來驗證,寫在 getStaticProps 中的原始碼永遠不會出現在客戶端的 JavaScript 程式碼中。

  • getStaticProps 只會在 next build 運行期間被執行
  • 當你設置了 fallback: truegetStaticProps 會在背景執行,
  • 當你設置了 fallback: blockinggetStaticProps 在初始渲染以前被執行,
  • 當你設置了 revalidategetStaticProps 會在背景執行
  • 當你設置了 revalidate()getStaticProps 會在背景依照需求執行

當結合 Incremental Static Regeneration 來使用時,getStaticProps 會在背景運行,同時對舊頁面做驗證,並將新頁面提供給瀏覽器。

使用 getStaticProps 從 CMS 取得資料

下面的範例示範了如何從 CMS 中取得文章列表。

// posts 會在建置期間時透過 getStaticProps() 產生 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` 這個 props return { props: { posts } } } export default Blog

getStaticProps 可使用的所有參數和 props 可以到 getStaticProps API reference 中參考。

直接撰寫伺服端原始碼

由於 getStaticProps 只會運行在伺服端而不是在客戶端,且甚至不會出現在瀏覽器的 bunlde.js,因此你可以在這裡直接對資料庫做查詢,不需要發送到瀏覽器。

這表示你可以直接在 getStaticProps 中撰寫伺服器端的原始碼,而不必用 getStaticProps來擷取對應的 API 路徑(這樣子做的意思等同於從外部取得內部資源)。

舉例來說,有一個 API 路徑是用來向 CMS 取得資料,如果直接用 getStaticProps 來呼叫這個 API 路徑的話,就會產生額外的開銷及降低效能。相反的,我們可以把從 CMS 擷取資料的這段邏輯放置在 /lib 資料夾,接著就能跟 getStaticProps 共用相同的邏輯。

// lib/load-posts.js // getStaticProps 與 API 路徑皆使用底下這個函式 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` 路徑 const posts = await loadPosts() // 被回傳的 props 將會傳入頁面元件 return { props: { posts } } }

或者,如果你沒有使用 API 路徑來擷取資料的話,可以直接在 getStaticProps 使用 fetch() 來擷取資料。

要驗證 Next.js 會從客戶端移除哪些東西,你可以使用 next-code-elimination tool

靜態生成 HTML 和 JSON

當一個頁面在建置期間使用 getStaticProps 來預先渲染時,除了產生 HTML 頁面之外,Next.js 還會生成一份 getStaticProps 執行結果的 JSON 檔案。

這份 JSON 檔案會被用於通過客戶端路由的 next/linknext/router。當你導覽到用 getStaticProps 預先渲染的頁面時,Next.js 會先擷取這份 JSON 檔案(已經在建置期間事先建置完成)並將其作為 props 提供給該頁面。這表示客戶端頁面的跳轉不會執行 getStaticProps,因為只是使用導出的 JSON 而已。

當使用 Incremental Static Generation 時,getStaticProps 將會在背景生成客戶端導覽所需的 JSON。你可能會從對相同頁面發出多次請求的形式來看到這一點,但是這是預期中的行為,並不會對最終用戶的效能上帶來影響。

該如何使用 getStaticProps

getStaticProps 只能從一個頁面裡輸出,你不能從非頁面的檔案裡輸出,像是 _app_document_error

會有這項限制的原因之一是因為 React 必須在頁面渲染以前就取得所有必須的資料。

除此之外,你必須把 getStaticProps 視為獨立的函式來使用-如果你把它添加為頁面元件的屬性,getStaticProps 將會無法運作。

注意:如果你已經建立了 custom app,請確保依照連結中的文件把 pageProps 傳至頁面元件,否則 props 將會是空的。

在開發期間執行每一次請求

在開發期間(next dev),getStaticProps 會在每次的請求中被執行。

預覽模式

你可以使用 預覽模式(Preview Mode) 來暫時繞過靜態生成且在請求期間渲染頁面。舉例來說,你可能正在使用一個 Headless CMS,並在草稿發佈之前預覽內容。

相關內容

想了解更多下一步該做什麼的資訊,我們建議閱讀下面幾個章節:

本篇文章由jubeatt

jubeatt

貢獻翻譯。瞭解如何參與貢獻