一文讀懂DOM渲染的演化過程

在這篇文章裏,DOM的渲染指的是對於瀏覽器中展現給用戶的DOM文檔的生成的過程。在Chrome中,這個渲染好的DOM,就是在開發者工具中元素這個tab中,遞歸的展開之後得到的整個文檔。

DOM渲染的演化過程,大致可以分爲可以分爲三個階段:

  • 純後端渲染
  • 純前端渲染
  • 服務端的js渲染結合前端渲染

下面我們分階段來做一下說明。

第一個階段是純後端渲染。採用這樣的渲染方式,就是每一個頁面中,在Chrome中展開得到的DOM,和服務器返回的DOM是基本一致的(可以通過查看網頁源代碼來得到服務器返回的DOM)。當然,這裏是“基本”一致,因爲實際操作中,頁面或多或少還是會帶有一些js代碼,並且在瀏覽器端中運行這些js代碼來對DOM進行的渲染,不過這一部分js代碼並不影響DOM的主體是由服務端返回的。純後端的DOM渲染,DOM樹的生成完全是在後端服務器中完成的,相當於後端服務器的程序會把各種的數據拼成一個DOM樹,並轉換成一個字節流作爲HTTP Response的body返回給瀏覽器。這種渲染的邏輯如下圖所示

 

純後端的渲染的整體的結構是最簡單的,把全部的邏輯都交給後端來完成。這樣的優點在於返回的HTTP Response是包含着全部頁面內容的,相對來說頁面的主體DOM結構都會在這個響應中返回,可以讓用戶更快的看到頁面的主體部分,而這樣的響應對於瀏覽器爬蟲來說也更有好,對SEO更有幫助。但是也正是由於這樣的簡單的結構,如果返回的DOM比較複雜,尤其是帶有複雜的交互的頁面,開發的難度就會非常大,或者說純後端渲染很難帶來良好的交互體驗。當然,在純後端DOM渲染中,地址的路由完全是由後端控制的(最簡單的例子就是有後端直接把服務器上的靜態目錄結構返回回來),每一次路由發生變化,都會引起頁面的刷新,這個使用體驗其實也不是很好。

btw,我們現在一般提到的“頁面”這個概念或者說法,就是在純後端DOM渲染的階段中形成並且延續下來的。在純後端的渲染中,可以很清晰的把一次DOM類型的HTTP請求作爲一個頁面。但是在後兩種方式中,這個分界就遠遠麼有這麼清晰了,前端框架只是實現了類似的“頁面”的效果,但是就不一定和某個具體的請求機制直接掛鉤了。

 

第二個階段就是純前端渲染,很大程度上,純前端渲染可以解決純後端渲染中出現的各種體驗問題。如下圖所示,純前端渲染把DOM生成的主題邏輯都放在了前端,這時後端只會返回一個框架的DOM結構,比如只帶一個容器元素的的DOM,然後由js代碼把頁面的主題渲染到這個容器元素中。

 

 

在純前端DOM渲染中,服務器主要是以API的形式返回各種數據,然後由js把數據重新組合成DOM。的大家耳熟能詳的各種前端框架,比如Vue.js,React.js,angularjs等等,主要都是以這種方式完成了對於DOM的渲染。相對於純後端的DOM渲染方式,純前端DOM渲染的方式形成了一個天然的表現層和數據層的分界,js代碼負責交互和展現,後端以API形式提供純粹的數據。這種改變帶來的最大的好處就是,交互的部分可以脫離數據接口獨立的開發和調試,讓站點的交互能力大幅的提升,並且很好的解耦了表現層和數據層的代碼邏輯。

在純前端DOM渲染中,第一屏的DOM渲染,依賴於大量的前端代碼的加載和一次到多次的API請求。請求本身處理的時間,加上http請求的round trip的時間,這就會讓第一屏的渲染之前有很多工作要做,並且每一步工作都帶着從用戶的網絡到服務器網絡的訪問延遲,如果用戶到服務器的物理距離很遠,這個延遲累加起來就會很大。很多優化的方法,比如控制max-age等緩存時間,通過MANIFEST來儲存靜態資源等,都是針對用戶第二次加載第一屏來進行的,無法解決用戶第一次加載第一屏的問題。

 

 

下面我們就看一下第三個階段,服務端的js渲染結合前端渲染,如下圖所示

 

 

 

可以說,這裏是把純前端渲染劃分成了兩個渲染的子階段。第一個子階段即SSR初步渲染完成DOM,也就是把我們上面說到的第一屏先在服務器端通過js渲染出來,這個子階段在服務器端增加了一個js渲染層的服務(比如next.js和nuxt.js),這一層相當於把原來要在客戶網絡與服務器網絡之間進行的大量通信轉移到了由服務器網絡與服務器網絡之間進行,大大縮減了網絡通信消耗的時間。第二個子階段就是前段渲染的階段,主要是解決首屏加載之後用用戶交互問題,這些都和純前端渲染時完全一致的。

第三個階段,主要是把前兩個階段中,一些交給純後端DOM渲染邏輯分離的不好,但是交給純前端DOM渲染又會造成較高延遲的部分單獨分離出來形成了一獨立DOM渲染階段,保留的代碼中天然的展示層和數據層的分離,又把API請求的累計延遲減少了很多,從SEO角度來說渲染結果對搜索引擎也很友好。當然,這樣的做法需要給整體的架構增加一個獨立的單元,給開發和部署都帶來了更高複雜性。

 

本文提到的DOM渲染的三種方式,雖然第三個階段最適於提供最優的使用體驗,但不一定實際開發中最佳的方式,在特定的場景下,可以根據場景的特性來選擇最簡單的方法來完成。比如在網絡延遲很低的情況下(內部網絡),就沒有必要選取服務器端js渲染的方式,純前端渲染就可以帶來低延遲的使用體驗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章