什麼是 CSR、SSR、SSG、ISR

2023-07-02 06:00:54

本文以 ReactVue 為例,介紹下主流的渲染模式以及在主流框架中如何實現上述的渲染模式。

前置知識介紹

看渲染模式之前我們先看下幾個主流框架所提供的相關能力,瞭解的可跳到下個章節。

掛載元件到 DOM 節點

這是主流框架最基本的能力,就是將元件渲染到指定的 DOM 節點上。在 React 中所使用的 APIrender,在 Vue 中所使用的是 createApp 後的 mount

水合

水合用來將元件渲染到已有的靜態內容上,用於為靜態頁面恢復其互動和動態能力。在 React 中所使用的 APIhydrateReact 18 前的版本) 和 createHydrateReact 18),在 Vue 中所使用的是 createSSRApp 後的 mount

Vue 中的 API 語意稍顯奇怪,因為使用 createSSRApp 的場景並不一定是 SSR

輸出渲染內容

主流框架除了可以將元件渲染到 DOM 節點上以外,還能將其要渲染的內容直接輸出為如 HTML 字串等形式。輸出為字串的 APIReactVue 中所使用的 API 都叫做 renderToString

React 中還推出了很多其它的 API:如 renderToStaticMarkuprenderToStaticNodeStream 等等。功能基本一致,不影響本文的內容所以此處不細說了。下面的例子中僅以 renderToString 為例。

主流渲染模式

知道了主流框架的這幾種能力,我們再來通過標題提到的幾種主流渲染模式看下他們能用來組合出什麼樣的效果,

CSR - Client Side Rendering - 使用者端渲染

CSR 就是我們常見的 SPA 所使用的渲染方式,所有的主流框架都支援,或者說:只要是在使用者端渲染過程中使用到了指令碼都可以算作使用者端渲染。

CSR 主要流程為:

  1. 瀏覽器載入頁面
  2. 載入對應的指令碼
  3. 指令碼執行時向頁面中渲染內容,此步驟一般包含兩種方式:
    1. 向一個空節點中渲染內容,一般應用於純粹的 CSR 應用。這裡使用的就是上面提到的掛載元件的功能。
    2. 向一個已有內容的節點中渲染內容,通常應用於 CSR 與其它渲染模式(SSRSSGISR)結合的場景下

CSR 的使用場景定義也很簡單,如果在使用者端頁面有動態需求或需要互動則必須使用。

SSR - Server Side Rendering - 伺服器端渲染

SSR 是另一個比較常見的渲染模式,使用這種渲染模式可以從伺服器端直接返回要渲染的靜態內容。

其常見流程為:

  1. 瀏覽器發起 HTTP 請求對應的頁面
  2. 伺服器端接收到請求後準備渲染頁面所需要的資料
  3. 將所需要的資料傳入需要渲染的頁面元件中然後通過 renderToString 輸出為靜態內容
  4. 拼接頁面模版、水合指令碼等將生成的靜態內容返回到瀏覽器,瀏覽器進行渲染
  5. 瀏覽器渲染內容,執行水合指令碼恢復頁面互動和動態能力

純粹的 SSR 指代的接收到請求、輸出靜態內容、返回瀏覽器的模式。水合的相關部分是屬於 CSR 的內容。

要注意水合並不是必須的,可以按需選擇。比如如果你的需求是要對不同的使用者展示不同的頁面,然而頁面上並沒有任何可以互動或動態的內容,那完全可以忽略水合的部分。

SSR 一般應用於以下場景:

  1. 出於首頁開啟速度、使用者體驗、SEO 等目的需要讓使用者更快的看到頁面首屏內容
  2. 想要預先渲染的頁面內容中存在動態的內容

SSG - Static Site Generation - 靜態站點生成

SSG 現在也比較常見,它所指代的是在構建階段就將頁面所需要的資料準備好然後將需要的頁面通過指令碼構建為靜態內容的模式。

其常見流程為:

  1. 在構建階段構建指令碼遍歷所有需要靜態構建的頁面
  2. 獲取渲染所需要的資料並通過 renderToString 輸出為靜態內容
  3. 將靜態內容拼接頁面模版和水合指令碼等內容後儲存到檔案中
  4. 瀏覽器發起請求時從伺服器端返回靜態頁面(一般直接使用靜態檔案伺服器即可)
  5. 瀏覽器渲染內容,執行水合指令碼恢復頁面互動和動態能力

純粹的 SSG 指代的同樣是不包含 CSR 部分的內容,即構建階段生成靜態頁面並在請求時直接將靜態頁面返回的過程。水合過程同樣不是必須的,視需求決定即可。

SSG 一般應用於以下場景:

  1. 出於首頁開啟速度、使用者體驗、SEO 等目的需要讓使用者更快的看到頁面首屏內容
  2. 頁面中基本都是靜態內容,變動很少或變動的時機比較固定

所以常用於通過 CMS 生成內容、部落格站點等靜態內容較多的場景。

ISR - Incremental Static Regeneration - 增量靜態再生

ISR 目前使用的不多,它算是 SSG 的一種增強版,指的是在 SSG 的基礎上,伺服器端在收到頁面請求時會對頁面的時效性進行判斷,如果認定失效則會對該頁面進行增量構建的一種模式。

其常見的流程如下:

可以看出 ISR 在構建和使用者端環節沒有任何的變化,而是增加了 Server 端的邏輯:

  1. 在伺服器端收到對應頁面請求時伺服器端會先返回當前內容然後對頁面做失效驗證
  2. 如果頁面實現,伺服器端會對失效的頁面進行後臺增量構建
  3. 當下次請求到達時如果新的頁面已經生成成功則會返回新頁面的內容,但在此之前還會繼續使用舊頁面的內容

當然上述的邏輯並不絕對,先增量構建再返回也同樣是 ISR,只是一般這樣會影響到使用者體驗一般不推薦。

ISR 適用的場景是:

  1. 網站匹配 SSG 場景
  2. 但對頁面有一定的實時性要求

比如說天氣預報頁面,可能半小時更新一次即可,或者是新聞頁面,在存在新資料時再進行增量構建也是一種解決方案。

如何選擇

在選擇渲染模式時我們通過以下邏輯進行簡單的判斷:

  1. 使用者端頁面是否需要動態或互動能力,如果要則 CSR 為必選
  2. 如果頁面有 SEO、首屏、效能等需求
    1. 如果頁面中想要靜態展示的內容對每次存取都可能存在差異——比如每個使用者看到的頁面資訊不同,則可以選擇 SSR
    2. 如果頁面中靜態展示的內容對每次存取沒有差異性即可選擇 SSG
      1. 如果頁面中的靜態內容變動較為頻繁,則可選擇 ISR

其次還要注意 SSRISR 都需要伺服器端的支援,所以如果只有靜態檔案伺服器那需要的改動就比較大了。

最後

渲染模式其實遠不止以上幾種,很多場景下都可以進行相應的優化。以下是一些我能想到的場景:

  • 在錄入或更新資料時通過 WebHook 等通知構建系統進行增量構建,算是 ISR 的一種變種
  • SSR 場景下可以對靜態元件和動態元件進行區分,將靜態元件使用 SSG 輸出,然後將其拼接到頁面中。

所以沒有最好的只有最適合的,按需選擇最適合自己需求的渲染模式即可。

如果想要看 SSRSSGISR 的具體實現請看我之前的文章。