如果你在一個頁面裡輸出了 getStaticProps
函式(靜態網頁生成),Next.js 將會在建置期間(build time)時透過 getStaticProps
回傳的 props 來預先渲染該頁面。
export async function getStaticProps(context) { return { props: {} // 會被當作 props 傳入頁面元件中 } }
注意不管是哪一種渲染類型,所有
props
的內容都會被傳入頁面元件中,且客戶端能透過 HTML 查閱。這是為了確保頁面能夠正確的注入(hydrated)內容。請確保你沒有把任何不應該出現在客戶端的敏感資訊放在props
中。
如果你符合下面的情況,你應該用 getStaticProps
:
getStaticProps
生成的 HTML
和 JSON
檔案能夠被快取成 CDN 提升效能getStaticProps
只會在伺服端執行而不是客戶端。你可以用 這個工具 來驗證,寫在 getStaticProps
中的原始碼永遠不會出現在客戶端的 JavaScript 程式碼中。
getStaticProps
只會在 next build
運行期間被執行fallback: true
,getStaticProps
會在背景執行,fallback: blocking
,getStaticProps
在初始渲染以前被執行,revalidate
,getStaticProps
會在背景執行revalidate()
,getStaticProps
會在背景依照需求執行當結合 Incremental Static Regeneration 來使用時,getStaticProps
會在背景運行,同時對舊頁面做驗證,並將新頁面提供給瀏覽器。
下面的範例示範了如何從 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。
當一個頁面在建置期間使用 getStaticProps
來預先渲染時,除了產生 HTML 頁面之外,Next.js 還會生成一份 getStaticProps
執行結果的 JSON 檔案。
這份 JSON 檔案會被用於通過客戶端路由的 next/link
或 next/router
。當你導覽到用 getStaticProps
預先渲染的頁面時,Next.js 會先擷取這份 JSON 檔案(已經在建置期間事先建置完成)並將其作為 props 提供給該頁面。這表示客戶端頁面的跳轉不會執行 getStaticProps
,因為只是使用導出的 JSON 而已。
當使用 Incremental Static Generation 時,getStaticProps
將會在背景生成客戶端導覽所需的 JSON。你可能會從對相同頁面發出多次請求的形式來看到這一點,但是這是預期中的行為,並不會對最終用戶的效能上帶來影響。
getStaticProps
只能從一個頁面裡輸出,你不能從非頁面的檔案裡輸出,像是 _app
、_document
或 _error
。
會有這項限制的原因之一是因為 React 必須在頁面渲染以前就取得所有必須的資料。
除此之外,你必須把 getStaticProps
視為獨立的函式來使用-如果你把它添加為頁面元件的屬性,getStaticProps
將會無法運作。
注意:如果你已經建立了 custom app,請確保依照連結中的文件把
pageProps
傳至頁面元件,否則 props 將會是空的。
在開發期間(next dev
),getStaticProps
會在每次的請求中被執行。
你可以使用 預覽模式(Preview Mode) 來暫時繞過靜態生成且在請求期間渲染頁面。舉例來說,你可能正在使用一個 Headless CMS,並在草稿發佈之前預覽內容。
想了解更多下一步該做什麼的資訊,我們建議閱讀下面幾個章節: