靜態網站生成 (SSG)
範例
- WordPress 範例(Demo)
- 使用 Markdown 檔案的部落格範例 (Demo 示範)
- DatoCMS 範例 (Demo 示範)
- TakeShape 範例 (Demo 示範)
- Sanity 範例 (Demo 示範)
- Prismic 範例 (Demo 示範)
- Contentful 範例 (Demo 展示)
- Strapi 範例 (Demo 展示)
- Prepr 範例 (Demo 展示)
- Agility CMS 範例 (Demo 展示)
- Cosmic 範例 (Demo 展示)
- ButterCMS 範例 (Demo 展示)
- Storyblok 範例 (展示)
- GraphCMS 範例 (展示)
- Kontent 範例 (展示)
- Builder.io 範例 (展示)
- TinaCMS 範例 (展示)
- 靜態推文 (展示)
- Enterspeed 範例 (Demo 展示)
如果頁面使用靜態生成 (Static Generation),頁面 HTML 會在建置時 (build time) 生成。這表示在生產環境中,當您執行 next build
時,就會生成頁面 HTML。接著,每次請求都會重複使用此 HTML。它可以由 CDN 快取。
在 Next.js 中,您可以使用或不使用資料來靜態生成頁面。讓我們來看看每種情況。
無資料靜態生成
預設情況下,Next.js 會使用無資料靜態生成預先渲染頁面。以下是一個範例:
function About() {
return <div>About</div>
}
export default About
請注意,此頁面不需要擷取任何外部資料即可進行預先渲染。在這種情況下,Next.js 會在建置期間為每個頁面生成一個 HTML 檔案。
使用資料靜態生成
有些頁面需要擷取外部資料才能進行預先渲染。有兩種情況,其中一種或兩種可能適用。在每種情況下,您都可以使用 Next.js 提供的這些函式:
- 您的頁面內容取決於外部資料:使用
getStaticProps
。 - 您的頁面路徑取決於外部資料:使用
getStaticPaths
(通常與getStaticProps
一起使用)。
情況 1:您的頁面內容取決於外部資料
範例:您的部落格頁面可能需要從 CMS(內容管理系統)擷取部落格文章列表。
// TODO: Need to fetch `posts` (by calling some API endpoint)
// before this page can be pre-rendered.
export default function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
為了在預先渲染時擷取這些資料,Next.js 允許您從同一個檔案匯出 (export)
一個名為 getStaticProps
的 async
函式。這個函式會在建置時被呼叫,並讓您在預先渲染時將擷取的資料傳遞給頁面的 props
。
export default function Blog({ posts }) {
// Render posts...
}
// This function gets called at build time
export async function getStaticProps() {
// Call an external API endpoint to get posts
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
的運作方式,請參閱資料擷取文件。
情境 2:您的頁面路徑取決於外部資料
Next.js 允許您使用動態路由建立頁面。例如,您可以建立一個名為 pages/posts/[id].js
的檔案,以根據 id
顯示單個部落格文章。這將允許您在訪問 posts/1
時顯示 id: 1
的部落格文章。
要瞭解更多關於動態路由的資訊,請查閱動態路由文件。
然而,您想要在建置時預渲染的 id
可能取決於外部資料。
範例:假設您只在資料庫中新增了一篇部落格文章(id: 1
)。在這種情況下,您只想在建置時預渲染 posts/1
。
稍後,您可能會新增第二篇文章,id: 2
。那麼您也需要預渲染 posts/2
。
因此,您預渲染的頁面路徑取決於外部資料。為了處理這個問題,Next.js 允許您從動態頁面(在這種情況下是 pages/posts/[id].js
)export
一個名為 getStaticPaths
的 async
函式。這個函式會在建置時被呼叫,並讓您可以指定要預渲染的路徑。
// This function gets called at build time
export async function getStaticPaths() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts')
const posts = await res.json()
// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// We'll pre-render only these paths at build time.
// { fallback: false } means other routes should 404.
return { paths, fallback: false }
}
同樣在 pages/posts/[id].js
中,您需要匯出 getStaticProps
,以便您可以擷取有關此 id
的文章資料,並使用它來預渲染頁面。
export default function Post({ post }) {
// Render post...
}
export async function getStaticPaths() {
// ...
}
// This also gets called at build time
export async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Pass post data to the page via props
return { props: { post } }
}
要瞭解更多關於 getStaticPaths
如何運作的資訊,請查閱資料擷取文件。
我應該在什麼時候使用靜態生成?
我們建議盡可能使用靜態生成(無論是否包含資料),因為您的頁面可以建置一次並由 CDN 提供服務,這比讓伺服器在每次請求時都渲染頁面要快得多。
您可以將靜態生成用於許多類型的頁面,包括:
- 行銷頁面
- 部落格文章和作品集
- 電子商務產品列表
- 說明和文件
您應該問自己:「我可以在使用者請求之前預渲染這個頁面嗎?」如果答案是肯定的,那麼您應該選擇靜態生成。
另一方面,如果您無法在使用者請求之前預渲染頁面,那麼靜態生成就不是一個好主意。也許您的頁面顯示經常更新的資料,並且頁面內容在每次請求時都會更改。
在這種情況下,您可以執行下列其中一項操作:
- 使用搭配客戶端資料擷取的靜態生成:您可以略過預渲染頁面的某些部分,然後使用客戶端 JavaScript 來填入它們。要瞭解更多關於這種方法的資訊,請查閱資料擷取文件。
- 使用伺服器端渲染:Next.js 會在每次請求時預渲染頁面。它會比較慢,因為頁面無法由 CDN 快取,但預渲染的頁面將始終保持最新狀態。我們將在下面討論這種方法。
這有幫助嗎?