ISR(Incremental Static Regeneration)是 Next.js 在(SSG)的基礎上做出的改進方法,讓頁面在構成之後根據需求進行重構,有助於提高網站性能。
ISR 的核心思想是:
下面是 ISR 的主要精神:
我們來擴充一下原本範例的功能,讓原本的表單長出各個角色細節的陳列頁面,透過 ISR 來完成以下功能:
// 路徑位置在 src/pages/characters/[id]/index.tsx
import { RickandmortyCharacter } from '@/pages'
import { GetStaticPaths, GetStaticProps } from 'next';
import { useRouter } from 'next/router'
import React, { useEffect, useState } from 'react'
// 我保留csr的部分讓大家好對比
// const Character = () => {
// const [roleDetail, setRoleDetail] = useState<RickandmortyCharacter | null>(null)
// const router = useRouter()
// useEffect(() => {
// const controller = new AbortController();
// const signal = controller.signal;
// fetch(`https://rickandmortyapi.com/api/character/${router.query.id}`, {
// signal: signal
// })
// .then((response) => response.json())
// .then((response: RickandmortyCharacter) => {
// // 成功之後的處理
// setRoleDetail(response)
// });
// return () => controller.abort();
// }, [router.query.id])
// return (
// <div>
// <h2>here is {router.query.id}</h2>
// <div>{roleDetail?.name}</div>
// </div>
// )
// }
// 下面是SSG/ISR
interface CharacterProps {
roleDetail: RickandmortyCharacter;
}
const Character: React.FC<CharacterProps> = ({roleDetail}) => {
const router = useRouter()
return (
<div>
<h2>here is {router.query.id}</h2>
<div>
<p>Name: {roleDetail?.name}</p>
<p>status: {roleDetail?.status}</p>
<p>species: {roleDetail?.species}</p>
<p>gender: {roleDetail?.gender}</p>
<p>origin: {roleDetail?.origin.name}</p>
<p>location: {roleDetail?.location.name}</p>
</div>
</div>
)
}
// 預先生成的路徑
export const getStaticPaths: GetStaticPaths = async () => {
const numArr = (num: number) => {
if (num > 0) {
let result = [];
for(let i = 1; i <= num; i++) {
result.push(i)
}
return result
}
}
// 這裡我本來就知道第一頁是1 - 20才這樣處理
const possibleIds = numArr(20);
const paths = possibleIds!.map((id) => ({
params: { id: id.toString() },
}));
return {
paths,
fallback: 'blocking',// 可以設定為 false, true, blocking
};
};
export const getStaticProps: GetStaticProps<CharacterProps> = async ({ params }) => {
const characterId = params?.id;
if (!characterId) {
return {
notFound: true,
};
}
const response = await fetch(`https://rickandmortyapi.com/api/character/${characterId}`);
const roleDetail: RickandmortyCharacter = await response.json();
return {
props: {
roleDetail,
},
revalidate: 60 // 代表每60秒會重發確認頁面資訊是否有異動需要重新生成
};
};
export default Character
在這個範例中:
getStaticPaths
和 getStaticProps
用於在構建時生成角色細節的靜態頁面。revalidate
選項表示在每次訪問頁面時,都會檢查是否需要重新生成頁面。在不考慮 CSR 的情況下,我們只能靠 SSR 或 SSG 來處理,在這兩種情况下,每次有新角色加入或更新時,我們必須重新構建整個網站,來確保所有頁面都是最新的。
不使用 ISR 的情況:
使用 ISR 的情况:
這就是實際使用上的差異,下一篇我們來講講SSR的部分。