2023/04/07 # 快速了解Next.js中的網頁渲染技術重點: SSR、SSG、ISR與CSR ## 前言 Next.js 是 React 的網頁框架。在學習使用 Next.js 開發的時候,我們會接觸到四種常見的網頁渲染技術。我們需要考量該選擇使用哪些網頁渲染技術,較為適合開發中的網站或應用程式。 先解釋一下這四種技術的英文縮寫: SSR:Server Side Rendering,伺服器端渲染 SSG:Static Site Generation,靜態網站生成 ISR:Incremental Site Rendering,增量式的網站渲染 CSR:Client Side Rendering,客戶端(通常是瀏覽器)渲染 ## Next.js pre-rendering 預渲染 Next.js 有一個特點是支援預渲染,預設會預渲染每個頁面,目的是可以帶來更好的性能以及 SEO。 Next.js 會將網站的所有頁面提前生成靜態 HTML 文件並保存下來,如此一來當使用者訪問網站時,伺服器會回傳預渲染好的靜態 HTML 文件,而不是使用 JavaScript 動態生成網頁內容。 Next.js 的預渲染又分為兩種形式,分別是**靜態網站生成 SSG(Static Site Generation)** 和**伺服器端渲染 SSR(Server Side Rendering)**。 ## SSR 伺服器端渲染 - 可以讓伺服器動態地注入資料到 HTML 的檔案中,讓客戶端第一次請求拿到的 HTML 就已經包含所有的資料,因此 google 爬蟲也就可以順利地爬到網站中的內容,利於 SEO。 - 因為每次請求都會重新生成頁面,使用 SSR 就必須有個伺服器一直處理使用者的請求,一直產生有資料的 HTML,並送到客戶端,這樣的工作對於伺服器來說是一個負擔。 - 適合需要經常展示更新數據資料的網站。 ### 獲取資料的方式 - 將在伺服器端的每個頁面請求中執行一個異步函數`getServerSideProps`以從 API 獲取資料。 - 載入頁面之前,首先將執行該函數並產生延遲,然後再為頁面提供服務。 ## SSG 靜態網站生成 - 所有的內容都在 **連結(build)** 的時候都打包進入檔案中,所以使用者在瀏覽網站時,就可以拿到完整的HTML檔案。 - 除了有利於 SEO 之外,還有因為每次使用者拿到的 HTML 內容都不會變,所以還可以讓 HTML 被 **cache** 在 CDN 上,很適合用在**資料變動較小**的網頁中,像是部落格、產品介紹頁這種應用中。 ### 獲取資料的方式 - 執行特殊函數:`getStaticProps`來獲取一次數據。 ## `getServerSideProps` vs. `getStaticProps` `getServerSideProps` 和 `getStaticProps` 是 Next.js 中用於資料預取的兩個函數: - getServerSideProps 會在每次請求時都重新取得資料,而 getStaticProps 則是在編譯時就取得資料,並將資料儲存在靜態檔案中。 - 使用 getServerSideProps 時,網頁的載入速度會比較慢,但是資料是最新的。 - 當使用 getStaticProps 時,網頁的載入速度會比使用 getServerSideProps 更快,但是資料可能不是最新的。 如果要網頁在每次請求時都重新取得資料,則應該使用 `getServerSideProps`。如果您需要在編譯時就取得資料,則應該使用 `getStaticProps`。如果您需要在編譯時就取得資料,但是又希望資料是最新的,則可以使用 `revalidate`屬性。 ## ISR 增量式的網站渲染 ISR基本上是SSG和SSR的結合體。在首次生成靜態頁面之後,有新數據時會重新生成該頁面。ISR適用於需要SEO最佳化和首次載入速度快且需要動態更新內容的網頁。 使用ISR需要在`getStaticProps`函數中添加`revalidate`屬性,並指定一個秒數,表示多久重新產生一次頁面。例如: `revalidate: 10` 表示每10秒重新產生一次頁面。 ### 獲取資料的方式 - 執行特殊函數: `getStaticProps` + `revalidate` ## CSR 客戶端渲染 - 只要上述的這些 API,例如 `getStaticProps` 、`getServerSideProps` ... 我們都沒有使用,數據都是通過在組件內部使用 `axios`或者`fetch`去發送請求獲取並渲染的,那麼我們使用的就是純客戶端渲染了。 - 這種方式與SSR是相對的,使用上需分離前後端。 - 渲染資料的所有過程都交由客戶端(瀏覽器)處理,使用者在瀏覽網站時,第一次跟伺服器請求的 HTML 檔裡面幾乎不包含任何的內容,伺服器並沒有傳入資料到 HTML。接著,後續會再透過載入的 bundle,也就是 JavaScript 的檔案,再讓 JS 執行 AJAX 跟伺服器請求資料,最後將資料渲染到畫面上,使用者會比較慢看到網頁的內容。 ### 獲取資料的方式 - 使用 `useEffect` 函數。 - 它會在客戶端的每個頁面請求中從 API 獲取數據(頁面被渲染後,函數將執行)。 ## 小結與簡單比較 - SSR 是在每次請求時動態地從 API 獲取數據並注入到 HTML 中,可以提高 SEO 效果,但會增加伺服器的負擔。適合用於需要經常展示更新數據的網站。 - SSG 是在 build 時就生成所有頁面和數據,可以提高性能和安全性,但不適合用於需要動態更新數據的網站。適合用於資料變動較小的網站。 - ISR 是在首次生成靜態頁面後,每當有新數據時會重新生成該頁面,可以結合 SSG 和 SSR 的優勢,既可以提高 SEO 效果和首次加載速度,又可以動態更新內容。適合用於需要 SEO 優化和首次加載速度快且需要動態更新內容的網站,且需要配置`revalidate`參數來控制更新頻率。 - CSR 是在 bundle 載入後才跟伺服器要數據,可以減少伺服器的負擔,但會降低 SEO 效果和首次加載速度。適合用於不需要 SEO 優化和首次加載速度快且需要前後端分離的網站。 ## 參考 - 官方文件 https://nextjs.org/docs/pages/building-your-application/data-fetching - 實驗非常仔細的fetch API loading比較 https://theodorusclarence.com/blog/nextjs-fetch-method https://theodorusclarence.com/blog/nextjs-fetch-usecase - 有範例參考的詳盡介紹 https://juejin.cn/post/7213653429415559223