前言
如果你曾寫過 Vue 或 React 這類型的前端框架,那麼多少會知道 SPA (Single-Page Application) 這個名詞,意思是網站僅存在一個頁面的應用程式,SPA 在頁面需要跳轉時不用等待整個網頁重整刷新,只需要從伺服器取得資料後渲染欲刷新的網頁中的部分元素即可,也因為這項特色成為了 SPA 的優點,除了能讓使用者瀏覽網頁的體驗能更佳順暢以外,也因為都是由前端結合 AJAX (Asynchronous JavaScript and XML) 技術發送 API 進行資料操作,進而實現讓前端與後端分離。
客戶端渲染 (Client-Side Rendering, CSR)
開頭所提及如 Vue 的這類將前後端進行分離的框架,因為僅專注在畫面上,所以通常都是 CSR,也就是所謂的客戶端渲染亦稱前端渲染。
以下是使用 Vue CLI 的預設配置,建立一個 Vue 3 的專案並啟動服務後,我們透過 Google Chrome 或 Edge 瀏覽器頁面中點擊右鍵後展開選單的「檢視網頁原始碼」功能後,所看到的網頁原始碼。
注意!這邊並不是「檢查元素」功能,而是針對伺服器請求首頁後,回傳的網頁 HTML;你也可以透過 cURL 等發送 Request 的工具,嘗試取的伺服器端回傳的網頁原始碼。
https://ithelp.ithome.com.tw/upload/images/20220916/20152617ZGijqIbXCf.png
可以發現到因為 CSR 的特點,首頁的網頁原始碼 <body></body> 中,僅有 <div id="app"></div> 這個元素,通常這個元素就是前端框架要準備 Mount 的根元素或容器,在包含 Vue 程式碼的 JavaScript 檔案尚未下載完畢與執行前,這個容器仍舊是空的,所以也就會導致網頁是一片空白的情況。
如下圖的流程,需要一直到 Vue 程式碼下載且載入完畢後,才能開始做請求初始資料與渲染 HTML 的動作,如果今天網路環境很差,伺服器雖然已經回應回來 HTML,不過在等待 JavaScript 檔案下載的過程中白畫面依舊會持續一段時間,直到完成下載與執行渲染後觸發畫面更新。
https://ithelp.ithome.com.tw/upload/images/20220916/20152617ki75eEM99p.png
客戶端渲染,指的「渲染」就是在客戶端渲染 HTML,這個渲染的動作,你也可以理解為產生或變動 HTML,瀏覽器再 依據變動後的 HTML 進行畫面的更新,也因為這個特性,框架可以做的到僅渲染部分 HTML,從而讓瀏覽器僅更新部分的畫面,達到更好的效能與體驗。
然而 CSR 最常為人詬病的一項缺點就是搜尋引擎最佳化 (Search Engine Optimization, SEO),一個網站上線後為了能在搜尋引擎上能有更好的排名與曝光,其中一個方式就是要為網站進行搜尋引擎最佳化的配置。SEO 配置與優化在 CSR 上比較難去實現,因為 CSR 是在客戶端進行資料請求後渲染 HTML 再由瀏覽器做畫面更新,導致搜尋引擎的爬蟲所蒐集與索引到的網站網頁的 HTML 並不包含客戶端所需要即時請求的資料,進而讓爬蟲無法解析到這些資料可能含有關鍵字等索引。雖然現今搜尋引擎的爬蟲遇到 CSR 類型的網站有部分能解決首次資料載入的問題且能收錄到資料,但仍有一些小細節仍不夠友好,綜觀來說 SPA 並不方便也不利於做 SEO 配置。
要解決 SEO 的問題,可以採用預渲染 (Pre-rendering) 的方式,讓網頁請求送達伺服器端後,返回的頁面即為已經包含資料的網頁 HTML,常見的有 Server-Side Rendering 和 Static Site Generation 等技術來解決 SEO 配置。
伺服器端渲染 (Server-Side Rendering, SSR)
SSR 伺服器端渲染或稱後端渲染,並不是為了解決 CSR 問題而存在的也不是什麼新奇的概念。
在網際網路與瀏覽器剛起步時,使用者的客戶端 (Client) 是與伺服器 (Server) 直接請求網頁檔案,例如 index.html,而檔案的內容即為 HTML 格式的網頁原始碼,並讓瀏覽器進行畫面的渲染繪製,我們先不考慮 JavaScript 進行互動與動態操作網頁的 HTML 元素,這裡的重點是──使用者請求某個網頁頁面後,所接收到 HTML 即是瀏覽器進行畫面渲染的最終網頁原始碼,由後端伺服器吐出最終的 HTML,雖然不是靠後端語言渲染 HTML ,但這不就也是伺服器端產生 HTML 的一種嗎!
再後來,隨著程式語言的發展,PHP、JSP 與 ASP/ASP.NET 等後端語言都是以 SSR 也就是伺服器端渲染為主,再回傳至前端。這一系列由前端發送網頁請求,後端接受到後透過後端程式碼在伺服器端執行、拿取資料庫資料等操作都在伺服端運算渲染完,再回傳至使用者的瀏覽器進行畫面的渲染繪製,也就稱之為伺服器端渲染,亦稱後端渲染。
搜尋引擎的出現,讓網站開發在實務上需要涵蓋很多關鍵字能搜尋到並讓網站在搜尋引擎的排名能越靠前,被點擊進入網站的機會就更高也就有更多的流量。
可以參考下圖的流程,SSR 與 CSR 不同,當使用者請求瀏覽頁面時,後端伺服器可能就已經包含了從資料庫或其他 API 拿取資料的動作,並在後端運算渲染完最終的初始頁 HTML 後,才回應至客戶端的瀏覽器,所以瀏覽器就可以依照 HTML 繪製出初始畫面,並同時等待 JS 下載完畢後執行後續需要進行網頁互動的流程。
https://ithelp.ithome.com.tw/upload/images/20220916/20152617WGDnkZuDVt.png
SSR 所產生的初始頁面就包含了資料而非空頁面,所以搜尋引擎的爬蟲就能正確的蒐集並建立索引資料或關鍵字,根據 SEO 優化規則,進而讓網站在搜尋引擎的排名能越靠前,被點擊進入網站的機會就更高,也就會有更多的流量;看看現在的部落格、網路新聞等這類的追求高曝光高流量的網站,多數都有使用到 SSR 的技術。
舉例來說 WordPress 這套常用於架設部落格或內容管理的系統,除了在架構彈性、社群生態完整外,WordPress 以 PHP 程式語言作為開發系統本身就是以 SSR 伺服器端渲染內容為主,在 SEO 優化上就本身就具有得天獨厚的條件與優點,也因此 WordPress 在架設網站仍佔有一席之地。
靜態頁面生成 (Static Site Generation, SSG)
SSG (Static Site Generation) 顧名思義就是產生靜態頁面的技術,使用 SSG 技術的網站通常在編譯打包時期就會連帶編譯產出靜態網頁,因此 SSG 非常適合做內容不大會變動的靜態網站,這些編譯出來的頁面也能上 CDN 被快取,不過也會因為網站大小而導致因為打包的時間可能過長,且在頁面內容需要改變,就必須要重新編譯打包,所以沒辦法像 CSR 或 SSR 具有動態內容的彈性。雖然 SSG 有一些缺點與劣勢,但也有 ISR (Incremental Static Regeneration) 等技術來解決。
CSR、SSR 與 SSG 的優缺點
客戶端渲染 (Client-Side Rendering, CSR)
優點
跳轉頁面時,不再需要由伺服器重新渲染整個頁面,前端框架會幫我們實現部分元素更新,使用者體驗較佳。
實現前後端分離,讓前端能更專注 UI 開發,後端專注 API。
因為渲染工作皆在客戶端完成,伺服器負擔也較小。
缺點
首次進入網站時,可能需要較長的下載 JS 與載入渲染時間會有白畫面問題。
不利於 SEO,搜尋引擎爬蟲蒐集資料時多數不執行 JS 或頁面過於複雜,而導致無法獲得初始頁面資料;搜尋引擎對於 CSR 雖有解決方案,但是仍不夠友善。
伺服器端渲染 (Server-Side Rendering, SSR)
優點
有利於 SEO,首次進入網站時,網頁 HTML 就已經在伺服器端渲染生成完畢,搜尋引擎爬蟲便能準確抓取最終網頁資料。
缺點
跳轉頁面時,網頁都需要再重新載入,導致用戶體驗較差。
因為渲染工作皆在伺服端完成,所以每次都需要重新取得整個頁面的 API 的資料與渲染,對於伺服器負擔也較大。
靜態頁面生成 (Static Site Generation, SSG)
優點
打包編譯時產生出網頁原始碼 HTML 檔案,即靜態資源檔案,因此能很好的搭 CDN 緩存來減輕伺服器負擔。
有利於 SEO,因為打包編譯時產生出網頁原始碼 HTML 檔案,正是可以讓搜尋引擎爬蟲解析的完整網頁資料。
缺點
如果頁面經常變動,就得再一次打包編譯,重新產生出新的一份網頁原始碼 HTML 檔案。
後端渲染再加上前端渲染行不行?
綜合上述,如果採用 SSR 渲染出首次進入富含資訊的網頁 HTML,再讓前端載入 Vue 做 CSR 讓其後續可以動態的取得資料更新畫面,那不就可以完美解決 SPA 常見的首頁白畫面或 SEO 優化問題了嗎?
沒有錯!這就是所謂的 SSR + SPA 也是目前常見的解決方案,而且透過前端 SSR 框架如 React 的 Next.js 或是本系列要介紹的 Nuxt 框架,就能同時兼具 SPA 的使用者體驗與 SSR 的 SEO 優化。
我們的網站運作流程就會變成:
瀏覽器首次進入網站,對伺服器發出請求。
由 Nuxt 接手請求,接著負責從資料庫資料或打 API 取得該頁面需要的資料,如文章的標題、內容。
接著將資料結合並渲染出 HTML,並將網頁 HTML 回傳給前端。
前端瀏覽器收到的請求回應 HTML,將繪製出網頁畫面,並從 SSR 切換成 SPA 讓前端接手渲染工作。
使用者與網頁進行互動,如切換頁面需要載入更多資料時,網頁從前端以 AJAX 發送 API 請求,再僅針對部分元素進行渲染 HTML 與觸發瀏覽器畫面更新。
雖然採用 SSR 的框架進行開發,勢必會有更耗費資源與效能的代價,但針對實務上的需求,這種方式仍是多數人所採納的解決方案。
DMCA Compliance - 內容侵犯 - Abuse 投訴