<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你聽(tīng)說(shuō)過(guò) No DomDiff 嗎?

          共 4947字,需瀏覽 10分鐘

           ·

          2021-09-25 17:21


          ?

          哈嘍,我是樹(shù)醬。今天分享鄭魚(yú)咚大佬的一篇文章,主要介紹虛擬Dom的實(shí)際應(yīng)用效果以及前沿前端框架像solid等是如何不使用虛擬dom解決問(wèn)題的等等

          ?

          前言

          ?

          前端框架經(jīng)過(guò)這幾年井噴式的發(fā)展,雖然各家依然是有自己的一套獨(dú)特風(fēng)格或特性,比如: 隨著v18的逐漸穩(wěn)定,react在追求異步渲染,快速響應(yīng)這條路上越走越遠(yuǎn);vue3則通過(guò)將reactive等更基礎(chǔ)底層的Api直接暴露給開(kāi)發(fā)者,這使得它在基于Proxy引擎構(gòu)建的Mutable響應(yīng)式編程上踐行的更加徹底... 但總體而言,框架的核心技術(shù)與特性都已十分趨同?,F(xiàn)在如果讓自己設(shè)計(jì)一個(gè)全新的前端框架, 也許會(huì)面臨以下抉擇:

          ?
          1.1 核心原理的選擇:
          • 整樹(shù)更新(immutable):更新時(shí),不關(guān)注是具體哪個(gè)狀態(tài)變化了,只要有狀態(tài)改變,直接整樹(shù)diff找出差異進(jìn)行對(duì)應(yīng)更新。代表框架:React。
          • 數(shù)據(jù)響應(yīng)式(mutable):更新時(shí),能夠精確知道是哪些狀態(tài)發(fā)生了改變,能夠?qū)崿F(xiàn)精確到節(jié)點(diǎn)級(jí)別的更新。vue、Svelte、SolidJS。
          1.2 更新粒度的選擇:
          • 應(yīng)用級(jí):有狀態(tài)改變,就更新整個(gè)應(yīng)用,生成新的虛擬Dom樹(shù),與舊樹(shù)進(jìn)行Diff。代表作:React,當(dāng)然了,現(xiàn)在它的虛擬Dom已升級(jí)為了Fiber。
          • 組件級(jí):與上方類似,只不過(guò)粒度小了一個(gè)等級(jí)。代表作:vuev2及之后的版本。
          • 節(jié)點(diǎn)級(jí):狀態(tài)更新直接與具體的更新節(jié)點(diǎn)的操作綁定。代表作vue1.x Svelte、SolidJS。
          1.3 是否采用虛擬Dom:

          這個(gè)選擇是與上邊采用何種粒度的更新設(shè)計(jì)緊密相關(guān)的:

          • 是:對(duì)應(yīng)用級(jí)的這種更新粒度,虛擬Dom簡(jiǎn)直是必需品,因?yàn)樵赿iff前它并不能得到此次更新的具體節(jié)點(diǎn)信息,必須要通過(guò)隨后的DomDiff篩選出最小差異,不然整樹(shù)append對(duì)性能是災(zāi)難。代表框架:React、vue, 但這里值得注意的事是:本質(zhì)上vue并不需要虛擬Dom,因?yàn)樗@種基于依賴收集的響應(yīng)式機(jī)制可以直接進(jìn)行節(jié)點(diǎn)級(jí)更新,但vue借助虛擬dom的抽象能力,可以做到更新粒度的隨意調(diào)整(目前是組件級(jí)),給vue的發(fā)展提供更多可能性, 尤其在跨平臺(tái)渲染方面,這點(diǎn)十分關(guān)鍵。
          • 否:對(duì)節(jié)點(diǎn)級(jí)更新粒度的框架來(lái)說(shuō),一般沒(méi)有必要采用虛擬dom。代表作:vue1.x Svelte、SolidJS。
          1.4 開(kāi)發(fā)語(yǔ)法DSL選擇:
          • JSX:React、SolidJS
          • 模版+編譯指令:vue(JSX可選)、Svelte
          1.5 其他支持特性:

          這點(diǎn)就比較瑣碎了,比如Suspence、Portals、Fragments、Context、Streaming SSR等。

          機(jī)智的你一定察覺(jué)到,這么多的技術(shù)選擇之間其實(shí)存在著某種緊密的聯(lián)系。這也不難理解,因?yàn)檫@些技術(shù)選項(xiàng)最終都是為框架的設(shè)計(jì)目標(biāo)服務(wù),正如vue追求的漸進(jìn)式、React追求的快速響應(yīng)。差異化競(jìng)爭(zhēng)在任何領(lǐng)域都存在,前端框架的世界也不例外??倳?huì)有后發(fā)制人的小眾流派去試圖挑戰(zhàn)一些權(quán)威實(shí)踐,用一些非常規(guī)的手段去直擊開(kāi)發(fā)者的痛點(diǎn),做出自己的差異化。最近在國(guó)外很火的SolidJS、Svelte就是這樣,一個(gè)類React、一個(gè)類vue,都是節(jié)點(diǎn)級(jí)、非虛擬Dom的框架代表,他們都宣稱在 性能 或者 獨(dú)立分發(fā)組件方面做出了自己的特色,接下來(lái)就帶你一探究竟。

          2 正文

          2.1 虛擬Dom是讓?xiě)?yīng)用變得更快還是更慢了?

          JS Framework Benchmark是一個(gè)評(píng)測(cè)JS框架性能的測(cè)試工具,類似于測(cè)試手機(jī)性能的跑分軟件,SolidJS的作者用這款工具測(cè)試了市面上幾乎所有JS框架,并跑出了第一的好成績(jī),詳細(xì)測(cè)試流程見(jiàn)它的官網(wǎng)。它究竟是怎么做到的呢?它的github首頁(yè)第一條特點(diǎn)就深深吸引了我的注意:

          一直以來(lái),虛擬Dom作為前端領(lǐng)域比較火的一個(gè)技術(shù),被認(rèn)為是提升js框架性能的利器。但是這其實(shí)是一直以來(lái)的誤解,在狀態(tài)與Dom操作之間抽象出一層虛擬Dom,需要犧牲一定的運(yùn)行時(shí)性能,并不一定比直接操作原生Dom快,要看情況,畢竟diff并不是免費(fèi)的。

          就拿引入虛擬dom較早的React來(lái)說(shuō),它可從來(lái)沒(méi)有說(shuō)過(guò) “React 比原生操作 DOM 快”。因?yàn)樗幕舅季S模式是每次有狀態(tài)變動(dòng)就重新“渲染"整個(gè)應(yīng)用。如果沒(méi)有 Virtual DOM,簡(jiǎn)單來(lái)想就是直接重置 "innerHTML"。很多人都沒(méi)有意識(shí)到,在一個(gè)大型列表所有數(shù)據(jù)都變了的情況下,重置 innerHTML 其實(shí)是一個(gè)還算合理的操作... 真正的問(wèn)題是在 “全部重新渲染” 的思維模式下,即使只有一行數(shù)據(jù)變了,它也需要重置整個(gè) innerHTML,這時(shí)候顯然就有大量的浪費(fèi)。這才是為什么要有 Virtual DOM的原因:它保證了

          • 1、 不管你的數(shù)據(jù)變化多少,每次重繪的性能都可以接受;
          • 2、 你依然可以用類似 innerHTML 的思路去寫(xiě)你的應(yīng)用。

          那回到問(wèn)題,虛擬Dom是讓?xiě)?yīng)用變得更快還是更慢了?這個(gè)需要分情況回答:

          • 初始渲染:Virtual DOM >  依賴收集
          • 小量狀態(tài)更新:依賴收集 >> Virtual DOM
          • 大量狀態(tài)更新:Virtual DOM > 依賴收集
          ?

          注意:上方的Virtual DOM是經(jīng)過(guò)memo|shoudUpdate極致優(yōu)化的情況,這里沒(méi)有具體的數(shù)據(jù)對(duì)比,是憑經(jīng)驗(yàn)判斷的,詳見(jiàn)尤大對(duì)這個(gè)問(wèn)題的回答。所以,虛擬Dom的出現(xiàn)并不總是為了幫助應(yīng)用更快,而是為了追求更重要的好處,提供過(guò)的去的性能,框架的設(shè)計(jì)永遠(yuǎn)是個(gè)道選擇題,在框架設(shè)計(jì)中尋求平衡-尤雨溪。并且隨著大型應(yīng)用承載的狀態(tài)越來(lái)越復(fù)雜,這種占用js主線程的運(yùn)行時(shí)diff會(huì)造成比較嚴(yán)重的頁(yè)面掉幀與卡頓,也需要對(duì)這種技術(shù)進(jìn)行優(yōu)化。這也是React要將v15中的同步遞歸Reconciler,花費(fèi)這么大代價(jià)重構(gòu)為Fiber的主要原因,既然對(duì)React的工作原理來(lái)說(shuō),虛擬Dom始終是躲不掉的一環(huán),那么它的思路就盡量壓榨這種技術(shù)的極限??梢?jiàn)即使強(qiáng)如react,也在這條路上走的并不平坦,那是不是可以徹底換個(gè)思維,比如:我不用虛擬Dom行不行?SolidJS: 完全可以。

          ?

          2.2 SolidJS簡(jiǎn)介

          類React框架很多,但SolidJS最像....

          這簡(jiǎn)直是React hooks的雙胞胎兄弟... 而且因?yàn)镾olidJS這種后發(fā)優(yōu)勢(shì),沒(méi)有React沉重的歷史包袱,比如不需要處理類組件的兼容(SolidJS只支持函數(shù)式)這讓它在實(shí)現(xiàn)了大部分React功能特性的前提下,源碼體積要比React小很多,這讓它在首屏加載方面就首先占據(jù)上風(fēng)。直接調(diào)用編譯好的DOM操作方法,省去了虛擬DOM比較這一步所消耗的時(shí)間,整個(gè)更新鏈路相比React變得簡(jiǎn)潔許多。

          這是React的調(diào)用棧

          這是SolidJS的

          筆者在試用這個(gè)框架一天之后,發(fā)現(xiàn)還是挺有意思的,總結(jié)起來(lái)有一下幾點(diǎn)。

          • 組件函數(shù)只會(huì)在整個(gè)應(yīng)用生命周期里調(diào)用一次。心智模型與React完全不一樣,反而與vue3保持了一致,可以說(shuō)兼具了React hooks+vue3的優(yōu)點(diǎn),
          • createEffect自動(dòng)追蹤依賴。

          在createEffect副作用回調(diào)執(zhí)行,依賴了A、B狀態(tài),但并沒(méi)有像React中那樣需要手動(dòng)維護(hù)一個(gè)dep數(shù)組。

          hook調(diào)用順序沒(méi)要求。也就是你可以在hook外層寫(xiě)嵌套了,喜大普奔。以函數(shù)調(diào)用的方式解決Proxy目標(biāo)必須是對(duì)象的問(wèn)題。比如上述例子中用getCountA()解決了vue3的ref.value煩惱,我個(gè)人認(rèn)為是要比.value更簡(jiǎn)潔一些。。。

          所以:SolidJS = React + vue3?這個(gè)答案見(jiàn)仁見(jiàn)智,但是它的響應(yīng)式實(shí)現(xiàn)確實(shí)是與vue一樣,都是基于發(fā)布訂閱的依賴收集去做的,但它沒(méi)有采用vue虛擬Dom的運(yùn)行時(shí)diff,而是充分在編譯階段做文章,將狀態(tài)更新編譯為獨(dú)立的DOM操作方法。這給它帶來(lái)了另一個(gè)優(yōu)勢(shì):有利于獨(dú)立分發(fā)組件。

          2.3 獨(dú)立分發(fā)組件

          這里我換另一個(gè)與Solid原理很類似的Svelte框架做示例,它比SolidJS的編譯時(shí)做的更加徹底。比如這段模板:

          <a>{{ msg }}</a>

          會(huì)被編譯成如下代碼:

          function renderMainFragment ( root, component, target ) {
           var a = document.createElement( 'a' );
           
           var text = document.createTextNode( root.msg );
           a.appendChild( text );
           
           target.appendChild( a )

           return {
            update: function ( changed, root ) {
             text.data = root.msg;
            },

            teardown: function ( detach ) {
             if ( detach ) a.parentNode.removeChild( a );
            }
           };
          }

          可以看到,跟基于 Virtual DOM 的框架相比,這樣的輸出不需要 Virtual DOM 的 diff/patch 操作,自然可以省去大量的運(yùn)行時(shí)代碼,所以,它對(duì)運(yùn)行時(shí)的依賴非常小,但是這有什么重要的呢?

          大家在項(xiàng)目開(kāi)發(fā)中,是否遇到過(guò)如下痛點(diǎn):

          A項(xiàng)目的某個(gè)組件與B項(xiàng)目的非常類似,但當(dāng)你想復(fù)用時(shí),發(fā)現(xiàn)一個(gè)是用React寫(xiě)的,一個(gè)是vue寫(xiě)的,技術(shù)棧并不統(tǒng)一,那么這種情況下除了重寫(xiě)之外,你想試圖通過(guò)將現(xiàn)有組件單獨(dú)打包,在A項(xiàng)目里直接引用編譯后的代碼。因?yàn)橄乱庾R(shí)會(huì)認(rèn)為編譯后的代碼總該是能復(fù)用了。但是卻忽略了重要一點(diǎn),無(wú)論是vue,還是react在編譯后的代碼里也是包含有比較重的運(yùn)行時(shí)的,主要就是虛擬dom的diff還有一些別的內(nèi)部api。那說(shuō)了這么多,上邊的問(wèn)題有什么實(shí)質(zhì)的解決方案嗎?答案是:「WebComponent」,這是w3c推動(dòng)的,與技術(shù)棧無(wú)關(guān)的一個(gè)組件標(biāo)準(zhǔn)。雖然現(xiàn)在看,它還不夠成熟,面臨許多的問(wèn)題要解決。但假如有一天,它的標(biāo)準(zhǔn)化及兼容問(wèn)題都解決了,這對(duì)Svelte這類的重編譯時(shí),幾乎不依賴運(yùn)行時(shí)的框架是一個(gè)非常大的利好。大家可以暢想一下,通過(guò)這類框架直接編譯一個(gè)WebComponent,處處都可以粘貼運(yùn)行,這是一件多么棒的事情。

          最后

          ?

          本文講了非采用虛擬Dom的框架的一些優(yōu)勢(shì),但它們也面臨因此帶來(lái)的一些不足,比如他們先天的因?yàn)槿鄙偬摂Mdom這層抽象,導(dǎo)致不利于跨平臺(tái)渲染;在真實(shí)的企業(yè)級(jí)項(xiàng)目中(非BenchMark的demo級(jí)別)性能是否比采用虛擬Dom更加優(yōu)秀,也是一個(gè)疑問(wèn),畢竟目前很少有大型項(xiàng)目拋棄主流而采用這么小眾的框架去試水。所以,目前主流的前端框架,在各自優(yōu)勢(shì)上深耕這么多年,不是那么容易說(shuō)顛覆就顛覆的,本文更多的是開(kāi)拓一下讀者的思路,兼聽(tīng)則明。

          ?

          請(qǐng)你喝杯?? 記得三連哦~

          1.閱讀完記得給?? 醬點(diǎn)個(gè)贊哦,有?? 有動(dòng)力

          2.關(guān)注公眾號(hào)前端那些趣事,陪你聊聊前端的趣事

          3.文章收錄在Github frontendThings 感謝Star?


          瀏覽 227
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  内射极品尤物 | 国产在线视频你懂的 | 伊人精品综合 | sese在线 | 人人操人人摸人人看 |