[note] React SSR
TL;DR
- Server-side Rendering(SSR)的重點在於使用者看到的 HTML DOM 是由 server 端產生好後才傳給 client。
- SSR 和 CSR 的最大差異是使用者最終 UI 上看到的 HTML DOM 元素是由 server 產生(SSR)、或是由 client(CSR)所產生
- SSR 和 SSG 最大的差異是在 HTML 檔案被建立、產生的時間點。SSR 會在每次收到 request 時才產生對應的 HTML,因此每次回傳 client 的 HTML 對 server 來說都是獨立不同的;但 SSG 是在一開始就把所有需要用到的頁面都建立出來,在收到 request 時就直接用相同、一開始就產生好的 HTML 回傳回去。
React SSR 基礎觀念
什麼是 Server-side Rendering (SSR)
SSR 會由 server 產出完整的 HTML 內容後才發送給 client。
傳統的全端框架(例如,Ruby on Rails)就是屬於 SSR,開發者會在 server 端讀取 database 的資料並放入 HTML 後才把頁面傳給 client。
如果畫面上有需要透過 API 才能取得的資料的話,server 則會同時扮演發送 API 的角色,由 server 發送 API 請求得到資料後,把資料放入 HTML 後,才傳給 client(參考 patterns.dev 上的影片)。
SSR vs. CSR
Pre-rendering and Data Fetching @ pjchender.dev
相較於 SSR 會由 server 將 HTML 的內容產生好後才回傳給 client,在 CSR(client-side rendering)中,server 收到 response 時只會回傳一個簡單的 HTML 模板給 client,後續使用者看到的內容則都是由 client 端的 JavaScript 所產生。
要辨別一個網站使用的是 SSR 或 CSR 最簡單的方式就是使用瀏覽器開發者工具的 「View Page Source」 功能(不能用 inspect,因為 inspect 看到的是已經透過 JavaScript 處理過的最終畫面):
- 如果 View Page Source 中看到的 HTML DOM 元素和實際 UI 上的幾乎一致,表示這個頁面是以 SSR 來處理;
- 反之,如果 View Page Source 中看到的是非常簡單的 HTML 樣板,和實際 UI 上看到的 DOM 差異很大,表示這個頁面走的是 CSR,UI 上看到的內容大部分都是透過 JavaScript 所產生。
SSR vs. SSG
Pre-rendering and Data Fetching @ pjchender.dev
除了 CSR 之外,還有一種是作法是使用 Static Side Generator(SSG)。SSG 和 SSR 的 HTML 都是由 server 產生好後提供給 client,但這兩者最大的差異在於,SSR 的 HTML 產生的時間點是沒錯 server 收到 request 後才開始製作,因此 server 每次收到 request 時都會需要產生一個獨立的頁面;而 SSG 則是在網頁打包時就把需要用到的 HTML 全部產生出來,server 每次收到 request 是都是回傳「相同的」、「一開始就產生好的」 HTML 檔給 client。
SSR vs. Universal (Isomorphic) JavaScript
在學習 Server Side Rendering 你有時也會聽到 Universal Javascript 或 Isomorphic Javascript,這幾個專有名詞的差別在於:
- Server Side Rendering:在伺服器端產出 HTML 後掛載到使用者的瀏覽器上。
- Universal JavaScript 或 Isomorphic JavaScript:兩者都是指在伺服器端所寫的部分程式碼,也會在瀏覽器上執行。強調的是在 client side 或 server side 應該有一致的撰寫風格。我們會先將要把 node 執行的程式碼透過 Webpack 和 Babel 重新編譯,因此在伺服器端也可以使用 ES6 的
import
語法。
❗ 在 SSR 中有一個非常重要的觀念,只有使用者第一次進來該頁面時是透過 Renderer Server 處理(SSR),除此之外,後續操作的行為和頁面的切換,則都是透過載好在瀏覽器端的 React APP 來處理。
SSR 的優缺點
- 由於 server 需要花更多資源來產生頁面,因此使用者得到 server response 的時間會長一些些(Time to First Byte, TTFB),特別是當使用者的網路不好、非常多使用者同時大量湧入、server 的程式碼沒寫好導致程式阻塞等情況時。
- 因為 server 會先產生好 mockup,可以減少 first paint 所需的時間(First Contentful Paint, FCP)
- 因為需要等到 JS 載入完,並執行 hydrate 後才能互動,因此有可能會增加 first interaction 的時間(Time to Interactive, TTI)
- 使用 SSR 對搜尋引擎的爬蟲比較友善,所以一般來說 SEO 會比較好
React SSR 基本實作
伺服器架構:前後端分離
一般來說在做 React SSR 的時候都會建議有兩個 Sever,也就是前後端分離的架構:
- API Server:用來處理商業邏輯、登入驗證、顯示使用者清單,一般所謂的後端。
- Renderer Server:用來轉譯應用程式並顯示給使用者,一般所謂的前端。
轉譯出 HTML 內容
在 ReactDOM 中除了提供我們 render()
的函式之外,另外提供了 renderToString()
的方法:
render()
:將所有元件(component)建立實例,並掛載(mount)到 DOM 節點上。renderToString()
:一次轉譯許多元件,並將 HTML 的結果以字串回傳。