Vue SSR 即時編譯技術

来源:https://www.cnblogs.com/coderhf/archive/2020/05/21/12931469.html
-Advertisement-
Play Games

當我們在服務端渲染 Vue 應用時,無論伺服器執行多少次渲染,大部分 VNode 渲染出的字元串是不變的,它們有一些來自於模板的靜態 html,另一些則來自模板動態渲染的節點(雖然在客戶端動態節點有可能會變化,但是在服務端它們是不變的)。將這兩種類型的節點提取出來,僅在服務端渲染真正動態的節點(se ...


 

當我們在服務端渲染 Vue 應用時,無論伺服器執行多少次渲染,大部分 VNode 渲染出的字元串是不變的,它們有一些來自於模板的靜態 html,另一些則來自模板動態渲染的節點(雖然在客戶端動態節點有可能會變化,但是在服務端它們是不變的)。將這兩種類型的節點提取出來,僅在服務端渲染真正動態的節點(serverPrefetch 預取數據相關聯的節點),可以顯著的提升服務端的渲染性能。

提取模板中靜態的 html 只需在編譯期對模板結構做解析,而判斷動態節點在服務端渲染階段是否為靜態,需在運行時對 VNode 做 Diff,將動態節點轉化成靜態 html 需要修改渲染函數的源代碼,我們將這種在運行時優化服務端渲染函數的技術稱作 SSR 即時編譯技術(JIT)。

JIT Diff 演算法

首要面對的問題是如何 Diff,完成這項工作需要兩個 VNode,其中一個通過 serverPrefetch / asyncData 載入動態數據,我們稱之為 Dynamic VNode,另一個未載入任何數據,我們稱之為 Static VNode。我們做了一個大膽的假設,對任何用戶來說,Static VNode 渲染出的 html 是一致的,並且 Static VNode 是 Dynamic VNode 的子集,不同用戶的差異點在 Static VNode 相對 Dynamic VNode 的補集當中。

以上假設對絕大部分的 Web 應用都是成立的,某些意料之外的情況將在文末做討論

Diff 的核心在於從 Staitc VNode 中標記 Dynamic VNode,下一次僅渲染被標記的 Dynamic VNode,Diff 演算法的技術示意圖如下所示

優化前的 Dynamic VNode 渲染流程圖如下

優化後的 Dynamic VNode 渲染流程圖如下

如何修改渲染函數的源代碼

修改渲染函數的難點在於如何建立 VNode 與源代碼的對應關係,否則我們無從得知需要優化的節點是哪段代碼生成的,這看起來非常困難。幸運的是 Vue 的模板語法提供了很不錯的約束,內置的編譯引擎也確保了渲染函數代碼結構可預測。

如下模板代碼編譯生成的渲染函數結構是有章可循的

 

 

 

 

執行 _c(xxx) 會生成一個 VNode 節點,解析 _c(xxx) 會生成一個固定結構的 AST,將 AST 與 VNode 做綁定,如果當前 VNode 為靜態節點,則修改對應的 AST,VNode 樹遍歷結束後再將 AST 轉化成可執行的代碼,代碼里便有了我們對 VNode 做的優化。詳細的技術實現可參考項目中的 patch.js 和 patch-context.js 文件。

如下流程圖演示了修改渲染函數源代碼的過程

一個簡單的例子如下

 

 

官方編譯器生成的代碼:

 

 

使用 SSR 即時編譯生成的代碼:

 

 

用法

 

 

createBundleRenderer 與官方同名函數介面一致,參考 vue ssr 指南

推薦使用 serverPrefetch 預取數據,也支持使用 asyncData 預取數據,參考 demo

哪些場景會導致優化失敗

cookie

不要在服務端渲染周期內使用 cookie,除非你確定此數據與用戶無關。可以在 serverPrefetch / asyncData 方法內使用 cookie,服務端渲染周期結束後也可以被使用,例如:mounted,updated 等等。

不推薦用法

 

 

推薦用法

 

 

v-for

v-for 指令建議用 dom 元素單獨包裹,不建議和其他組件併排使用,由於 for 迴圈會擾亂抽象語法樹與 VNode 節點的對應關係,除非 v-for 指令所在的整個節點層級全為靜態,否則將不會對包含 v-for 指令的層級及子級做優化。

不推薦用法

 

 

推薦用法

 

 

閉包

某些場景下,渲染函數引用了閉包變數,同時這個閉包變數又影響著一個動態的節點,通過 ast 逆向生成的渲染函數暫時無法追蹤到之前的閉包引用,執行時會因找不到變數而報錯,碰到這種情況,解析引擎將放棄當前組件的 ast 優化,轉而使用優化前的渲染函數。

不推薦用法

 

 

推薦用法

 

 

為此,為了學好前端,創建了一個學習交流,能夠與大家一起學習、交流。大家免費領取面試題,電子書籍,特效項目源碼等乾貨。

 

先奉上一些資料圖:

 

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MINA MINA 是在微信中開發小程式的框架。其目標是通過儘可能簡單、高效的方式讓開發者可以在微信中開發具有原生 APP 體驗的服務。 MINA 提供了自己的視圖層描述語言 WXML 和 WXSS,以及基於 JavaScript 的邏輯層框架,核心是一個響應的數據綁定系統。整個系統分為視圖層(Vi ...
  • 1、添加音樂播放器(例如 網易雲音樂) 【html5 音樂播放器】 源碼 GitHub - MoePlayer/APlayer: Wow, such a beautiful HTML5 music player 中文使用指南 https://aplayer.js.org/#/zh-Hans/?id= ...
  • 為什麼需要構建工具? 轉換 ES6 語法 轉換 JSX CSS 首碼補全/預處理理器器 壓縮混淆 圖⽚片壓縮 前端構建演變之路 ant + YUI Tool grunt gulp、fis3 webpack、rollup、parcel 為什麽選擇 webpack? 社區⽣生態豐富 配置靈活和插件化擴展 ...
  • static 預設屬性,當position為預設值時會忽視top,left,right,bottom和z index的設置 relative 相對定位,相對正常位置進行偏離,通過top,left,right,bottom和z index設置元素的位置及層級,元素懸浮,脫離位置偏移,==但其在文本流里 ...
  • 【參考資料】 Bootstrap 中文文檔 ·——Bootstrap 是世界上最流行的、移動設備優先的、響應式前端開發框架。 https://v3.bootcss.com/ 全局 CSS 樣式 · Bootstrap v3 中文文檔 【CSS】 https://v3.bootcss.com/css/ ...
  • 一、簡介 該框架已經幫你寫好了很多頁面樣式,你如果需要使用,只需要下載它對應文件,之後直接cv拷貝即可 在使用Bootstrap的時候所有的頁面樣式都只需要你通過class來調節即可 版本選擇建議使用v3版本:https://v3.bootcss.com/ 【註意】 bootstrap的js代碼是依 ...
  • 在做移動端網站時,有時因技術問題或其他原因無法製作響應式版面,而移動端頁面只能放到子目錄下,但是手機端通過搜索引擎進入網站電腦端子頁面,無法匹配到移動端頁面,使得用戶體驗很不好,即影響排名也影響轉化。這裡有一個js代碼可以實現用戶使用手機訪問電腦端,自動跳轉到對應手機頁面。舉例:一個pc頁面http ...
  • 動畫 參考閱讀: https://www.cnblogs.com/xiaoyuanqujing/articles/11670140.html 插件機制(乾貨滿滿) 參考閱讀: https://www.cnblogs.com/xiaoyuanqujing/articles/11670482.html ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...