嗨大家!昨天跟大家分享了四種網頁渲染方式,那今天來講講該怎麼用 Next.js 實作~ 在 Next.js 裡,抓取資料的方式會影響到渲染方式。上一篇提到 Next.js 提供的三個 functions 就是用來抓取資料做預渲染 (產生包含內容資料的 HTML 檔案) 的,我們一起看下去~
注意:想要用這三個 functions 的話,一定要在 Next.js 的 page (頁面) 檔案裡面做 export 喔。
注意:這三個 functions 會在 server (伺服器) 端跑完,因此我們可以在裡面寫後端程式碼,甚至操作資料庫。
getStaticProps
(Static Generation)這 function 會在 build time 的時候跑而抓取所需要的資料,就是當我們執行 npm run build
的時候跑的。這 function 可以回傳 props
object (物件) 當該 page 的 props,這 page 需要的資料就透過 props 傳進去的。伺服器跑完這 function 之後,除了產生了 HTML 檔案之外,還會產生了 JSON 檔案。為什麼呢?因為在 client-side (客戶端) 切換頁面的時候,瀏覽器會讀這 JSON 檔案裡面的資料用來顯示 page 內容。
// 在 build time 的時候跑在伺服器端
export async function getStaticProps() {
// 可以直接抓取資料或是操作資料庫
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
// 傳給該 page 的 props
props: {
posts,
},
// 過了 10 秒之後,可以重新驗證/重新產生
revalidate: 10,
}
}
getStaticProps
接收 context
當 parameter,而 context
包含渲染該 page 的相關資訊,可以在這裡看官方的 docs。getStaticProps
回傳一個物件而裡面包含:
props
(optional):傳給 page 當該 page 的 props
revalidate
(optional):實作 ISR 用的,如果設定 false 代表只會 build 一次,就是整個專案跑 npm run build
的時候。如果設定秒數,代表過幾秒之後可以重新 generate (產生) 這 page 做 revalidation (重新驗證) 更新 page 的資料。不過伺服器會先回傳 cache 裡的舊 page 給瀏覽器然後在背後 revalidate 完才回傳最新的 page 給瀏覽器,讓瀏覽器去做更新notFound
(optional):找不到資料的時候,決定是否回傳 404 的 status code 與 error pageredirect
(optional):設定是否要導頁而且導去哪裡,用物件的形式 { destination: string, permanent: boolean }
或是 { destination: string, statusCode: number }
getStaticProps
會在 build time 的時候跑在伺服器端,把抓取到的資料塞進該 page 對應到的 HTML 檔案,讓 HTML 檔案包含了資料內容,而可以直接丟給瀏覽器去顯示,這就是 SSG。如果設定了 revalidation
的秒數,該 page 會進行重新驗證/重新產生的過程,這是 ISR。
不過,如果在 dynamic (動態) routes 的 page 裡有用到 getStaticProps
,那需要搭配 getStaticPaths
才能正確運作,可以去下一段看看為什麼~
getStaticPaths
(Static Generation)一樣會在伺服器端 build time 的時候跑的,名字跟上一個 function 也有點像,雖然用途不一樣,可是這兩個 function 常常用在一起。這 function 抓取資料的目的並不是變成網頁的內容,而是用這些資料決定需要產生哪些 dynamic (動態) routes 的 HTML 檔案。
export async function getStaticPaths() {
return {
paths: [
{ params: { id: '1' } },
{ params: { id: '2' } }
],
fallback: true, false, or 'blocking'
};
}
getStaticPaths
回傳一個物件而裡面包含:
paths
(required):決定要產生哪些 paths 的 HTML 檔案,每個 path 是一個物件包含 params
物件。如果你的 path 是 posts/[id]
而 id
是動態的,那 params
裡面要定義 id
的值。所以上面那段 code 只會去產生兩個 HTML 檔案,pages/posts/1.html
和 pages/posts/2.html
fallback
(required):決定找不到 page 的時候的行為,總共有三種方法
true
:當 page 不在 paths
裡面,伺服器會回傳一個備份版本的 page,而該 page 可能是空的或是 loading 狀態 (由我們決定),然後伺服器在背後去產生該 page 的 JSON 檔案,等到完成之後再傳給瀏覽器去做顯示,也會把這新產生的 page 放在 CDN 的 cache 裡false
:如果該 page 不在 paths
裡面,而找不到該 page 的 HTML 檔案,會拿到 404 error code 而顯示 404 error page'blocking'
:當 page 不在 paths
裡面,伺服器會產生該 page 的 HTML 檔案而這段期間瀏覽器是等待的狀態 (白畫面),等到 HTML 檔案產生完才回傳給瀏覽器做顯示。這一次伺服器是採用 SSR 的方式,不過產生完之後,HTML 檔案一樣會被放到 CDN 的 cache 裡getStaticPaths
會在 build time 的時候跑在伺服器端,把抓取到的資料決定該產生 dynamic routes 的哪些 paths。這些 paths 再往裡面跑每個 page 的 getStaticProps
產生 HTML 和 JSON 檔案。沒有 getStaticPaths
就不會有 dynamic routes 相關的 page 了!
getServerSideProps
(Server-side Rendering)最後一個!這 function 很像 getStaticProps
,回傳的值差不多,一樣在伺服器端跑。不一樣的點是它不是 build 的時候跑的,而是每次有 request (請求) 的時候才會跑。跟 getStaticProps
也一樣除了會產生 HTML 檔案之外,還會產生了 JSON 檔案。
export async function getServerSideProps(context) {
return {
props: {}, // 傳給該 page 的 props
}
}
getServerSideProps
接收 context
當 parameter,而 context
包含渲染該 page 的相關資訊,可以在這裡看官方的 docs。getServerSideProps
回傳一個物件而裡面包含:
props
(optional):傳給 page 當該 page 的 props
notFound
(optional):找不到資料的時候,決定是否回傳 404 的 status code 與 error pageredirect
(optional):設定是否要導頁而且導去哪裡,用物件的形式 { destination: string, permanent: boolean }
或是 { destination: string, statusCode: number }
getServerSideProps
會在每一次的 request time 的時候跑在伺服器端,把抓取到的資料塞進該 page 對應到的 HTML 檔案,讓 HTML 檔案包含了資料內容,而可以直接丟給瀏覽器去顯示,這就是 SSR。產生檔案的過程中,瀏覽器會顯示白畫面,所以使用者可能會覺得顯示很慢,而且 SSR 產生的 HTML 檔案不會自動被 CDN 做 cache (需要特別設定喔~)。
以上三個 function 都是跑在伺服器端抓取資料,可是如果需要一直更新資料或是不需要 SEO,那其實可以採用 CSR,在 client-side (客戶端) 去抓取資料~ 這部分跟一般在寫 React 需要拿資料的時候一模一樣,可能就是在 useEffect
去抓取資料然後畫面顯示 loading 狀態!
今天講的好像有點多XD
明天跟大家分享 Next.js 中的 pages 與 routing!也就是會講到 dynamic routes 的部分喔 :)
祝大家中秋節快樂!
晚安 <3