「乾貨」你須要瞭解的六種渲染模式

背景

週末在網上衝浪, 看到個消息:NextJS 9.3 將靜態站點生成功能引入了NextJS平臺。html

靜態站點生成, 也就是所謂的 SSG : Static Site Generationreact

喝了口水,順便回憶了下如今的幾種渲染模式:web

  1. SSR (Server Side Rendering)
  2. SSG (Static Site Generation)
  3. SSR With hydration
  4. CSR with Pre-rendering
  5. CSR (Client Side Rendering)
  6. Trisomorphic Rendering

都不是什麼新鮮玩意, 就總結複習一下, 順便分享給你們, 但願能給各位帶來一些啓發。瀏覽器

正文

1. SSR (Server Side Rendering)

SSR, 服務端渲染。緩存

服務器呈現響應於導航爲服務器上的頁面生成完整的HTML。這樣能夠避免在客戶端進行數據獲取和模板化的其餘往返過程,由於它是在瀏覽器得到響應以前進行處理的。服務器

服務器渲染一般會產生快速的 First Paint (FP)和 First Contentful Paint (FCP)。網絡

在服務器上運行頁面邏輯和呈現能夠避免向客戶端發送大量JavaScript,這有助於實現快速的交互時間 (TTI)。ide

這是有道理的,由於使用服務器渲染,實際上只是將文本和連接發送到用戶的瀏覽器。工具

這種方法能夠在很大範圍的設備和網絡條件下很好地工做,而且能夠帶來有趣的瀏覽器優化,例如流文檔解析。post

該圖顯示了影響FCP和TTI的服務器渲染和JS執行

流程:

瀏覽器 --> 服務器 --> 服務器執行渲染 --> index.html(實時渲染的內容)) --> Render --> bundle.js + images --> Render

image-20191231111204363

優勢

  • 內容當即可用 -由於將HTML發送給客戶端,因此幾乎會當即看到頁面內容。
  • 無需獲取其餘客戶端 -理想狀況下,服務器呈現過程將進行全部必需的調用以獲取數據,所以不會從客戶端進行任何其餘服務調用。
  • 很是適合SEO

缺點

  • 服務器上的速度較慢 -須要渲染兩次頁面:一次在服務器上,一次在客戶端上。同事也可能正在從服務器進行服務調用以呈現頁面,全部這些都須要時間,所以可能會延遲HTML向客戶端的初始發送。
  • 與某些UI庫不兼容 -若是你用的某些庫使用了window,那你就要想辦法來解決了。 由於 Node 中沒有window 或者 document

2. SSG (Static Site Generation)

SSG:靜態網站生成。

靜態網站生成相似於服務器端渲染,不一樣之處在於您在構建時而不是在請求時渲染頁面。

與服務器渲染不一樣,因爲沒必要動態生成頁面的HTML,所以它還能夠實現始終如一的快速到第一字節的時間。

一般,靜態呈現意味着提早爲每一個URL生成單獨的HTML文件。

藉助預先生成的HTML響應,能夠將靜態渲染器部署到多個CDN,以利用邊緣緩存的優點。

該圖顯示了影響FCP和TTI的靜態渲染和可選的JS執行

優勢

  • 內容當即可用 -由於將HTML發送給客戶端,因此幾乎會當即看到頁面內容。
  • 無需獲取其餘客戶端 -理想狀況下,服務器呈現過程將進行全部必需的調用以獲取數據,所以不會從客戶端進行任何其餘服務調用。
  • 很是適合SEO
  • -靜態內容的呈現速度速度很是快。
  • 沒有服務器 -沒必要運行服務器。

缺點

  • 大型站點可能會很慢 -若是路由不少,速度可能會變慢。
  • 與某些UI庫不兼容 -若是你用的某些庫使用了window,那你就要想辦法來解決了。 由於 Node 中沒有window 或者 document

3. SSR With hydration

hydration, 直譯爲水合

讓人一臉懵逼。

簡單點講, 將功能放回到已經在服務器端中呈現的HTML中的整個過程,稱爲水合。

換句話說就是,對曾經渲染過的HTML進行從新渲染的過程稱爲水合。

此方法試圖經過同時進行客戶端渲染和服務器渲染,達到一種平衡。

導航請求(例如整頁加載或從新加載)由服務器處理,該服務器將應用程序呈現爲HTML,而後將JavaScript和用於呈現的數據嵌入到生成的文檔中。

理想狀態下,就能夠像服務器渲染同樣實現快速的First Contentful Paint,而後經過使用稱爲(re)hydration的技術在客戶端上再次渲染來修補

這是一個新穎的解決方案,可是它也可能具備一些至關大的性能缺陷。

帶水合的SSR的主要缺點是:

即便改進了First Paint,它也可能對可交互時間產生重大負面影響。

SSR的頁面一般看起來具備欺騙性,而且具備交互性,可是在執行客戶端JS並附加事件處理程序以前,實際上沒法響應輸入

在移動設備上可能要花費幾秒鐘甚至幾分鐘。

原理示意:

該圖顯示客戶端渲染會對TTI產生負面影響

與JS致使的延遲互動相比,這個模型形成的問題可能會更加嚴重:

服務器響應導航請求返回了應用程序UI的數據描述。同時,但它還返回了用於組成該UI的源數據以及該UI的實現的完整腳本,該腳本隨後在客戶端啓動。

僅在bundle.js完成加載和執行後,該UI纔會變爲可交互。

舉個例子:

包含序列化UI,內聯數據和bundle.js腳本的HTML文檔

藍色部分包含了初始的3個checkbox, 以及須要加載的bundle.js,

一開始, 你會當即看到UI, 等bundle加載並執行完成以後, 頁面纔會更新, 進入可交互狀態。

從真實網站中收集的效果指標代表, 使用SSR水合模式效果並很差,強烈建議不要使用它。

緣由歸結爲用戶體驗:最終很容易使用戶陷入怪異的山谷

4. CSR with Pre-rendering

Pre-render 原理是: 在構建階段就將html頁面渲染完畢,不會進行二次渲染。

也就是說,當初打包時頁面是怎麼樣,那麼預渲染就是什麼樣。

等到JS下載並完成執行,若是頁面上有數據更新,那麼頁面會再次渲染。這時會形成一種數據延遲的錯覺。

Pre-render 利用 Chrome 官方出品的 Puppeteer 工具,對頁面進行爬取。

它提供了一系列的 API, 能夠在無 UI 的狀況下調用 Chrome 的功能, 適用於爬蟲、自動化處理等各類場景。

它很強大,因此很簡單就能將運行時的 HTML 打包到文件中。

原理是: 在 Webpack 構建階段的最後,在本地啓動一個 Puppeteer 的服務,訪問配置了預渲染的路由,而後將 Puppeteer 中渲染的頁面輸出到 HTML 文件中,並創建路由對應的目錄。

以此, 達到預渲染的目的。

流程:瀏覽器 --> 服務器 --> index.html(預渲染的內容) --> Render --> bundle.js + images --> Render

image-20191231113759430

5. CSR (Client Side Rendering)

CSR, 顧名思義, 客戶端渲染。

客戶端渲染,意味着: 直接使用JavaScript在瀏覽器中渲染頁面

全部邏輯,數據獲取,模板和路由均在客戶端而不是服務器上處理

CSR 示意圖:

該圖顯示了影響FCP和TTI的客戶端渲染

流程:瀏覽器 --> 服務器 --> index.html(白屏) --> bundle.js --> images --> Render

image-20191231113956671

優勢

  • 在服務器上快速 -由於僅呈現空白頁,因此呈現速度很是快。
  • 支持靜態 -空白頁能夠經過S3之類的服務靜態生成和提供,從而使速度更快。
  • 支持單頁應用程序 -客戶端渲染是惟一支持單頁應用程序或SPA的模型。
  • 成本相對較低 - CSR 相對於SSR/SSG, 更容易開發/維護。

缺點

  • 沒有初始渲染 -若是應用很大,或者客戶的鏈接速度很慢,加載時間過長,用戶體驗就不太好。

6. 三態渲染

若是你能夠結合Service-Worker, 則三態渲染模式也可能派上用場。

在三態渲染模型中,可使用服務器流式渲染進行初始導航,而後讓service worker 在 html加載完成後,繼續進行導航html的渲染。

這樣可使緩存的組件和模板保持最新狀態,並啓用SPA樣式的導航,以在同一會話中呈現新視圖。

若是能夠在服務器,客戶端頁面和service worker之間共享相同的模板和路由代碼時,這種方法十分有效。

三態渲染模型:

三態渲染圖,顯示瀏覽器和服務程序與服務器進行通訊

7. 服務端渲染 VS 客戶端渲染

服務器渲染會爲每一個URL按需生成HTML,比僅提供靜態渲染內容要慢。

同時,也有一些優化空間: 服務器渲染+ HTML緩存能夠大大減小服務器渲染時間。

服務器渲染的優點在於:與靜態渲染相比,它可以提取更多"實時"數據並響應更完整的請求集。

總結

從 SSR -> CSR, 以及中間不一樣的渲染模式, 都在圖裏:

該圖顯示了本文介紹的各類選擇

本文中介紹的6種渲染模式,至於如何選擇, 這裏也給出一些不成熟的建議:

  1. 對seo要求不高,同時對操做需求比較多的項目,好比一些管理後臺系統,建議使用 CSR。由於只有在執行完bundle以後, 頁面才能交互,單純能看到元素, 卻不能交互, 意義不大, 並且SSR 會帶來額外的開發和維護成本。
  2. 若是頁面無數據,或者是純靜態頁面,建議使用pre-render。 由於這是一種經過預覽打包的方式構建頁面,也不會增長服務器負擔。
  3. 對seo和加載速度有比較大需求的,同時頁面數據請求多的狀況,建議使用 SSR

結尾

好了,天都黑了,大概就是這麼多。

才疏學淺, 若有錯誤, 歡迎留言指正。

週末在研究 Reciol.js, 以爲挺有意思, 後面大概會出一篇分析的文章, 敬請期待哦。

參考資料

相關文章
相關標籤/搜索