getStaticPaths
當從使用動態路由的頁面匯出名為 getStaticPaths 的函式時,Next.js 將靜態預渲染 getStaticPaths 指定的所有路徑。
import type {
InferGetStaticPropsType,
GetStaticProps,
GetStaticPaths,
} from 'next'
type Repo = {
name: string
stargazers_count: number
}
export const getStaticPaths = (async () => {
return {
paths: [
{
params: {
name: 'next.js',
},
}, // See the "paths" section below
],
fallback: true, // false or "blocking"
}
}) satisfies GetStaticPaths
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
}getStaticPaths 返回值
getStaticPaths 函式應返回一個包含以下必需屬性的物件
paths
paths 鍵決定哪些路徑將被預渲染。例如,假設你有一個使用動態路由的頁面,名為pages/posts/[id].js。如果你從這個頁面匯出 getStaticPaths 併為 paths 返回以下內容:
return {
paths: [
{ params: { id: '1' }},
{
params: { id: '2' },
// with i18n configured the locale for the path can be returned as well
locale: "en",
},
],
fallback: ...
}那麼,Next.js 將在 next build 期間使用 pages/posts/[id].js 中的頁面元件靜態生成 /posts/1 和 /posts/2。
每個 params 物件的值必須與頁面名稱中使用的引數匹配
- 如果頁面名稱是
pages/posts/[postId]/[commentId],那麼params應該包含postId和commentId。 - 如果頁面名稱使用捕獲所有路由,例如
pages/[...slug],那麼params應該包含slug(這是一個數組)。如果這個陣列是['hello', 'world'],那麼 Next.js 將靜態生成路徑為/hello/world的頁面。 - 如果頁面使用可選捕獲所有路由,則使用
null、[]、undefined或false來渲染最根部的路由。例如,如果為pages/[[...slug]]提供slug: false,Next.js 將靜態生成頁面/。
params 字串是區分大小寫的,理想情況下應進行規範化以確保路徑正確生成。例如,如果引數返回 WoRLD,則只有當訪問路徑實際是 WoRLD 時才匹配,而不是 world 或 World。
除了 params 物件之外,當配置了國際化時,可以返回一個 locale 欄位,該欄位配置生成路徑的語言環境。
fallback: false
如果 fallback 為 false,則任何未由 getStaticPaths 返回的路徑都將導致一個 404 頁面。
當執行 next build 時,Next.js 將檢查 getStaticPaths 是否返回了 fallback: false,然後它將只構建 getStaticPaths 返回的路徑。此選項適用於要建立的路徑數量較少,或者不經常新增新頁面資料的情況。如果你發現需要新增更多路徑,並且設定了 fallback: false,則需要再次執行 next build 才能生成新路徑。
以下示例為名為 pages/posts/[id].js 的每個頁面預渲染一篇部落格文章。部落格文章列表將從 CMS 獲取並由 getStaticPaths 返回。然後,對於每個頁面,它使用 getStaticProps 從 CMS 獲取文章資料。
function Post({ post }) {
// Render post...
}
// 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 }
}
// 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 } }
}
export default Postfallback: true
示例
如果 fallback 為 true,則 getStaticProps 的行為將按以下方式更改:
- 從
getStaticPaths返回的路徑將在構建時由getStaticProps渲染為HTML。 - 在構建時尚未生成的路徑不會導致 404 頁面。相反,Next.js 將在第一次請求此類路徑時提供頁面的“回退”版本。網路爬蟲(例如 Google)不會獲得回退頁面,而是會像
fallback: 'blocking'那樣處理該路徑。 - 當透過
next/link或next/router(客戶端)導航到帶有fallback: true的頁面時,Next.js 將不會提供回退,而是會像fallback: 'blocking'那樣處理該頁面。 - 在後臺,Next.js 將靜態生成請求路徑的
HTML和JSON。這包括執行getStaticProps。 - 完成後,瀏覽器會收到生成路徑的
JSON。這將用於使用所需的 props 自動渲染頁面。從使用者的角度來看,頁面將從回退頁面切換到完整頁面。 - 同時,Next.js 將此路徑新增到預渲染頁面列表。後續對同一路徑的請求將提供已生成的頁面,就像在構建時預渲染的其他頁面一樣。
須知:使用
output: 'export'時,不支援fallback: true。
何時使用 fallback: true 很有用?
如果你的應用有大量依賴資料的靜態頁面(例如非常大的電子商務網站),那麼 fallback: true 會非常有用。如果你想預渲染所有產品頁面,構建時間會非常長。
相反,你可以靜態生成一小部分頁面,並將其餘頁面使用 fallback: true。當有人請求尚未生成的頁面時,使用者將看到帶有載入指示器或骨架元件的頁面。
不久之後,getStaticProps 完成,頁面將使用請求的資料進行渲染。從現在開始,所有請求相同頁面的使用者都將獲得靜態預渲染的頁面。
這確保了使用者始終擁有快速的體驗,同時保持了快速構建和靜態生成的好處。
fallback: true 不會更新已生成的頁面,為此請參閱增量式靜態再生。
fallback: 'blocking'
如果 fallback 為 'blocking',則 getStaticPaths 未返回的新路徑將等待 HTML 生成,與 SSR 完全相同(因此稱為 blocking),然後快取以供將來請求使用,這樣每個路徑只需生成一次。
getStaticProps 的行為如下:
- 從
getStaticPaths返回的路徑將在構建時由getStaticProps渲染為HTML。 - 在構建時尚未生成的路徑不會導致 404 頁面。相反,Next.js 將在第一次請求時進行 SSR 並返回生成的
HTML。 - 完成後,瀏覽器會收到生成路徑的
HTML。從使用者的角度來看,它將從“瀏覽器正在請求頁面”過渡到“完整頁面已載入”。不會出現載入/回退狀態的閃爍。 - 同時,Next.js 將此路徑新增到預渲染頁面列表。後續對同一路徑的請求將提供已生成的頁面,就像在構建時預渲染的其他頁面一樣。
預設情況下,fallback: 'blocking' 不會更新已生成的頁面。要更新已生成的頁面,請結合 fallback: 'blocking' 使用增量式靜態再生。
須知:使用
output: 'export'時,不支援fallback: 'blocking'。
回退頁面
在頁面的“回退”版本中
- 頁面的 props 將為空。
- 使用路由器,你可以檢測是否正在渲染回退頁面,
router.isFallback將為true。
以下示例展示了 isFallback 的用法
import { useRouter } from 'next/router'
function Post({ post }) {
const router = useRouter()
// If the page is not yet generated, this will be displayed
// initially until getStaticProps() finishes running
if (router.isFallback) {
return <div>Loading...</div>
}
// Render post...
}
// This function gets called at build time
export async function getStaticPaths() {
return {
// Only `/posts/1` and `/posts/2` are generated at build time
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
// Enable statically generating additional pages
// For example: `/posts/3`
fallback: true,
}
}
// 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 },
// Re-generate the post at most once per second
// if a request comes in
revalidate: 1,
}
}
export default Post版本歷史
| 版本 | 更改 |
|---|---|
v13.4.0 | App Router 現已穩定,並簡化了資料獲取,包括 generateStaticParams() |
v12.2.0 | 按需增量式靜態再生 已穩定。 |
v12.1.0 | 添加了按需增量式靜態再生(Beta)。 |
v9.5.0 | 穩定的增量式靜態再生 |
v9.3.0 | 引入了 getStaticPaths。 |
這有幫助嗎?