前言
當建構一個網頁的時候,最首要面對的問題就是「網頁內容要怎麼生成並提交給用戶?」,而為了解決這個問題所產生的解決方法就是「網頁渲染模式 (Rendering Pattern)」。
這個問題看似簡單但背後卻有許多種不同的抉擇需要納入考量,選擇正確的網頁渲染模式對用戶體驗(UX)和開發者體驗(DX)都至關重要。本系列文章將會介紹不同的網頁渲染模式,並且透過比較幫助你選擇合適的網頁渲染模式建構網頁。
良好 UX 的依據
為了創造良好的使用者體驗,就必須使用客觀的指標數值來衡量網頁體驗並修補潛在的缺點,Google 提出的網頁核心指標與相關的指標就是很好的方式:
首次位元組時間
測量網頁載入過程中從請求一個資源到第一個位元組回應所需的時間
首次內容繪製
測量網頁載入過程中首個內容的出現所需的時間
最大內容繪製
測量網頁載入過程中「首個最大內容的出現所需的時間」
可互動時間
測量網頁要花多久時間讓用戶可以與網頁互動
累積布局偏移
測量網頁內容位置變換的頻繁程度
首次輸入延遲
測量網頁要花多久時間去回應用戶的互動
良好 DX 的依據
為了創造良好的開發者體驗,確保開發時的效率與品質,以下是一些可以引領開發者更好開發的架構特質:
快速的建構時間
專案可以被快速的迭代與開發
低伺服器營運成本
縮減與最佳化伺服器的執行時間
可輕鬆回朔
專案部屬可以輕鬆的回朔到先前的狀態
可被即時訪問
用戶總是能在任何時候參訪你的網站
動態內容
頁面可以有效的加載動態內容
可被擴張的架構
專案可以在不陷入效能問題的前提下輕易的延伸或縮減規模
接著參照以上的指標與特性就可以開始比較不同的網頁渲染模式之間的差異與特點了。
靜態網站 Static Website
靜態網站是預先將網頁文件放置在伺服器上,當用戶請求網頁時伺服器就回傳網頁文件給用戶,伺服器不做任何運算處理,就是單純的回應用戶請求的檔案,由於網頁內容是寫死的,因此靜態網站最大的問題是更新動態的內容會需要手動編輯或嘗試使用靜態渲染來生成新的文件。
靜態渲染 Static Rendering
靜態網站可以由靜態渲染的方式來生成,透過自動化的工具例如: Jekyll、Hugo、11ty……等靜態生產器(Static Site Generator)將資料與介面分離,並透過模板引擎(Template Engine)生成網頁文件,這樣的模式也被稱為靜態生產(Static Site Generation)。
相較於手動編輯靜態網站,使用靜態生產器渲染可以更有效率的更新與管理網頁,但仍然有幾個問題需要注意:
🙋🏻♀️ 問題一:網頁動態內容如何呈現?
由於靜態渲染的網頁內容都是預先渲染好的,想要再額外顯示動態的內容是個問題,這時候可以考慮幾種應對模式:
- 使用伺服器動態的生成並回應每一頁面請求:伺服器渲染 SSR
- 在客戶端動態加載內容:靜態渲染加上客戶端獲取資料
🙋🏻♂️ 問題二:生成時間過久該怎麼辦?
渲染大量的頁面容易花費極大的時間成本,特別是在大量頁面的情況下,由於靜態網站的頁面都是預先生成好的,因此每次更新網站內容時都需要重新生成「整個網站的所有頁面」,這時候可以考慮幾種應對模式:
- 讓頁面只在被索求的時候由伺服器生成:增量靜態生產 Incremental Static Regeneration
靜態渲染加上客戶端獲取資料 Static With Client-Side fetch
在靜態渲染的基礎上使用 Ajax 的方式,在客戶端使用 JavaScript 來送出請求獲得資料並更新內容,這樣就可以在靜態網站中加入動態內容了,但仍需考慮幾點問題:
LCP - 如果內容沒有及時加載就可能會導致渲染畫面最大內容的時間過長
CLS - 如果沒有提供合適尺寸的 畫面骨架 就會導致布局偏移
- 伺服器營運成本 - 動態資料需要在每次頁面加載的時候被索取
- 可被即時訪問 - 需要等待動態內容渲染完畢才能看到完整內容
- 可伸縮的架構 - 須留意動態資料伺服器的擴張性
伺服器渲染 Server-Side Rendering
伺服器渲染是指在用戶每次請求網頁時,伺服器都會重新生成網頁內容並回傳給用戶,由於頁面及時生成需要時間,因此伺服器渲染的網站通常會比靜態網站慢,但也因為如此,伺服器渲染的網站可以輕易的加入動態內容在頁面之中。
TTFB:由於每請求一個頁面就會需要伺服器重新生成,引此勢必會更久
FCP、LCP、TTI、FID :由於等待伺服器重新生成,勢必會比預先渲染好頁面的靜態網站慢,這些達成這些指標的時間也可能會更久
- 伺服器營運成本:由於每次請求都需要重新生成,因此伺服器的負擔會更重
- 是否可回朔:都是即時依據當前資料生成頁面,因此回朔到先前的頁面狀態會較為困難
- 可被即時訪問:當伺服器無法運作時,就無法存取任何頁面
客戶端渲染 Client-Side Rendering
客戶端渲染是指使用 JavaScript 渲染整個頁面在瀏覽器上,當用戶請求網頁時,伺服器只會回傳一個空白的 HTML 檔案,並藉由客戶端 JavaScript 來動態生成網頁內容。
增量靜態生產 Incremental Static Regeneration
增量靜態生產是基於靜態生產的改良,用於解決大量頁面導致建構時間長、動態資料無法即時呈現的問題。在 ISR 中,只會事先渲染部分重要頁面,剩餘的頁面就等到有用戶請求再渲染,也有作法是在指定的時間由伺服器重新渲染該頁面,就可以定期的刷新靜態頁面中的內容。
- 伺服器營運成本:需要一個伺服器在背後持續的渲染新頁面,相較於完全的靜態生成會有維持伺服器的開銷
總結
基本上渲染的機制的差別主要還是在於:「渲染的時機是在伺服器還是客戶端?」、「是預先渲染好還是動態生成?」,而這兩個問題的答案就是網頁渲染模式的核心。如果是預先渲染好的網頁通常都會有更友善的 SEO,因為搜尋引擎爬蟲可以輕易的解讀現成的網頁文件,也會在客戶端有更好的效能,但代價是伺服器要多下工夫。
參考資料
- Rendering Patterns - patterns.dev
- Rendering Patterns - JavaScript Patterns
- 10 Rendering Patterns for Web Apps - Beyond Fireship
- Rendering on the Web