<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>

          尤雨溪:重頭來過的 Vue 3 帶來了什么?

          共 5525字,需瀏覽 12分鐘

           ·

          2020-06-06 23:21

          (給前端大學加星標,提升前端技能.

          作者:尤雨溪,翻譯:CSDN

          在過去的一年里,Vue團隊一直在開發(fā)Vue.js的下一個主要版本Vue 3,我們希望能在2020年上半年將其發(fā)布(在撰寫本文時,這項開發(fā)工作正在進行中)。

          重寫Vue新的主要版本的構(gòu)想是在2018年底形成的,當時Vue 2的代碼庫大約已有兩年半的運行歷史。這看起來不像是通用軟件生命周期中的一段很長的時間,但在這段時間里,前端環(huán)境發(fā)生了巨大的變化。

          兩個關(guān)鍵的因素導(dǎo)致了我們考慮重寫Vue新的主要版本:

          1. 主流瀏覽器對新的JavaScript語言特性的普遍支持。

          2. 當前Vue代碼庫隨著時間的推移而暴露出來的設(shè)計和體系架構(gòu)問題。


          1、為什么要重寫?

          ???使用新的語言特性

          隨著ES2015標準的發(fā)布,Javascript(正式稱為ECMAScript,簡稱ES)得到了重大改進,主流瀏覽器終于開始為這些新添加的特性提供適當?shù)闹С?。其中一些特性特別地為我們提供了極大提升Vue能力的機會。

          其中一個最值得注意的特性是Proxy,它允許框架攔截針對對象(屬性)的操作。Vue的一個核心特性是能夠監(jiān)聽對用戶定義的狀態(tài)所做的更改,并對DOM進行響應(yīng)式地更新。Vue 2通過使用getter和setter來替換有狀態(tài)對象的屬性,來實現(xiàn)這種響應(yīng)式的更新。切換到Proxy方式將允許我們消除Vue現(xiàn)有的限制(例如無法檢測新的屬性添加),并提供更好的性能。

          然而,Proxy是一個原生語言特性,在傳統(tǒng)瀏覽器中這個特性無法用polyfill來兼容。因此,為了利用這個特性,我們必須調(diào)整Vue框架的瀏覽器支持范圍,這是一個重大的突破性的改變,只能在新的主要版本中發(fā)布。

          ???解決體系架構(gòu)存在的問題

          在維護Vue 2的過程中,我們積累了一些由于現(xiàn)有體系架構(gòu)的限制而難以解決的問題。例如,模板編譯器的編寫方式使得正確的源映射(source-map)支持非常具有挑戰(zhàn)性。另外,雖然Vue 2在技術(shù)上支持構(gòu)建針對非DOM平臺的更高級別的渲染器,但為了實現(xiàn)這一點,我們必須分叉代碼庫并復(fù)制大量代碼。在當前的代碼庫中修復(fù)這些體系架構(gòu)問題將需要風險巨大的重構(gòu)工作,而這些重構(gòu)幾乎等同于重寫。

          同時,我們還積累了技術(shù)債務(wù),表現(xiàn)為各種模塊的內(nèi)部和似乎不屬于任何地方的浮動代碼之間的隱式耦合。這使得孤立地理解代碼庫的一部分變得更加困難,我們注意到貢獻者中很少有人有信心做出大范圍的更改。重寫將使我們有機會帶著這些問題和想法來重新考慮整個代碼庫結(jié)構(gòu)。


          2、初始原型的構(gòu)建階段

          我們在2018年底開始Vue 3的原型開發(fā),初步目標是驗證這些問題的解決方案。在這一階段,我們主要致力于為進一步開發(fā)打下堅實的基礎(chǔ)。

          ???切換到TypeScript

          Vue 2最初是用純ES(Javascript)寫成的。在原型設(shè)計階段之后不久,我們意識到一個類型系統(tǒng)(Type system)對于這樣一個規(guī)模的項目非常有用。類型檢查(Type check)大大減少了在重構(gòu)過程中引入意外錯誤的機會,并幫助貢獻者更有信心進行大范圍的更改。我們采用了Facebook的Flow type checker,因為它可以逐漸添加到現(xiàn)有的純ES項目中。Flow type checker在一定程度上起到了幫助作用,但我們并沒有從中得到我們所希望的那么多好處。特別是,持續(xù)的重大改變使得升級成為一種痛苦。相比較TypeScript與Visual Studio Code集成開發(fā)工具的深度集成,F(xiàn)low type checker對集成開發(fā)環(huán)境的支持也不理想。

          我們還注意到,用戶越來越多地同時使用Vue和TypeScript。為了支持它們的用例,我們必須獨立于使用不同類型系統(tǒng)的源代碼來編寫和維護TypeScript聲明。切換到TypeScript將允許我們自動生成聲明文件,從而減輕維護負擔。

          ???解耦內(nèi)部包

          我們還采用了monorepo設(shè)置,其中框架由內(nèi)部包組成,每個包都有各自的API、類型定義和測試程序。我們希望能夠使這些模塊之間的依賴關(guān)系更加明確,以便開發(fā)人員能夠更容易地閱讀、理解和更改所有模塊。這是我們努力降低項目貢獻障礙和提高其長期可維護性的關(guān)鍵。

          ???設(shè)置RFC(征求修正意見)流程

          到2018年底,我們已經(jīng)成功構(gòu)建了一個可工作的原型,它帶有新的響應(yīng)式系統(tǒng)和虛擬DOM渲染器。我們已經(jīng)驗證了我們想要進行的內(nèi)部架構(gòu)改進,但是面向公眾的API的更改還停留在草稿階段。是時候把它們變成具體的設(shè)計了。

          我們知道我們必須盡早并且小心地處理這件事。Vue的廣泛采用意味著任何重大改變都可能導(dǎo)致用戶的巨大遷移成本和潛在的生態(tài)系統(tǒng)碎片化。為了確保用戶能夠提供關(guān)于這些重大改變的反饋,我們在2019年初采用了RFC(征求修正意見)流程。每個RFC都使用一個模板,重點關(guān)注動機、設(shè)計細節(jié)、權(quán)衡和采用策略。由于該過程是在GitHub repo中進行的,我們將我們建議的更改作為pull請求提交,因此討論以評論的形式有效地展開了。

          事實證明,RFC流程非常有效,它作為一個思想框架,迫使我們充分考慮潛在變化的方方面面,并允許我們的社區(qū)參與設(shè)計過程,提交深思熟慮的功能請求。


          3、更快更小

          性能對前端框架至關(guān)重要。盡管Vue 2號稱具有良好的性能,但重寫提供了一個機會,可以通過試驗新的渲染策略來更提供更好的性能。

          ???克服虛擬DOM的瓶頸

          Vue有一個相當獨特的渲染策略:它提供類似于HTML的模板語法,但是,它是將模板編譯成渲染函數(shù)來返回虛擬DOM樹。Vue框架通過遞歸遍歷兩個虛擬DOM樹,并比較每個節(jié)點上的每個屬性,來確定實際DOM的哪些部分需要更新。由于現(xiàn)代JavaScript引擎執(zhí)行的高級優(yōu)化,這種有點暴力的算法通常非??焖伲荄OM的更新仍然涉及許多不必要的CPU工作。當你看到一個基本上是靜態(tài)內(nèi)容、只有少量動態(tài)綁定的模板時,效率低下的情況尤其明顯,因為這時候仍然需要遞歸地遍歷整個虛擬DOM樹,以找出需要更改的內(nèi)容。

          幸運的是,模板編譯步驟使我們有機會對模板執(zhí)行靜態(tài)分析并提取有關(guān)動態(tài)部分的信息。Vue 2在某種程度上是通過跳過靜態(tài)子樹來實現(xiàn)的,但是過于簡單的編譯器體系架構(gòu)使得更高級的優(yōu)化很難實現(xiàn)。在Vue 3中,我們使用適當?shù)腁ST轉(zhuǎn)換管道重寫編譯器,這允許我們以轉(zhuǎn)換插件的形式將編譯時(compile-time)優(yōu)化組合進來。

          隨著新的體系架構(gòu)的出現(xiàn),我們希望找到一種能夠盡可能減少開銷的渲染策略。一種選擇是拋棄虛擬DOM并直接生成命令式DOM操作,但這樣做會消除直接編寫虛擬DOM渲染函數(shù)的能力,而我們發(fā)現(xiàn)這種能力對于高級用戶和庫的編寫者非常有價值。另外,這將是一個巨大的突破性改變。

          另一個更好的辦法是去掉不必要的虛擬DOM樹遍歷和屬性比較,這在更新期間往往會產(chǎn)生最大的性能開銷。為了實現(xiàn)這一點,編譯器和運行時需要協(xié)同工作:編譯器分析模板并生成帶有優(yōu)化提示的代碼,而運行時盡可能獲取提示并采用快速路徑。這里有三個主要的優(yōu)化:

          首先,在DOM樹級別。我們注意到,在沒有動態(tài)改變節(jié)點結(jié)構(gòu)的模板指令(例如v-if和v-for)的情況下,節(jié)點結(jié)構(gòu)保持完全靜態(tài)。如果我們將一個模板分成由這些結(jié)構(gòu)指令分隔的嵌套“塊”,則每個塊中的節(jié)點結(jié)構(gòu)將再次完全靜態(tài)。當我們更新塊中的節(jié)點時,我們不再需要遞歸遍歷DOM樹 - 該塊內(nèi)的動態(tài)綁定可以在一個平面數(shù)組中跟蹤。這種優(yōu)化通過將需要執(zhí)行的樹遍歷量減少一個數(shù)量級來規(guī)避虛擬DOM的大部分開銷。

          其次,編譯器積極地檢測模板中的靜態(tài)節(jié)點、子樹甚至數(shù)據(jù)對象,并在生成的代碼中將它們提升到渲染函數(shù)之外。這樣可以避免在每次渲染時重新創(chuàng)建這些對象,從而大大提高內(nèi)存使用率并減少垃圾回收的頻率。

          第三,在元素級別。編譯器還根據(jù)需要執(zhí)行的更新類型,為每個具有動態(tài)綁定的元素生成一個優(yōu)化標志。例如,具有動態(tài)類綁定和許多靜態(tài)屬性的元素將收到一個標志,提示只需要進行類檢查。運行時將獲取這些提示并采用專用的快速路徑。

          綜合起來,這些技術(shù)大大改進了我們的渲染更新基準,Vue 3有時占用的CPU時間不到Vue 2的十分之一。

          注:CPU時間指的是執(zhí)行JavaScript計算所花費的時間,不包括瀏覽器DOM操作。

          ???最小化bundle的大小

          框架的大小也會影響其性能。這是Web應(yīng)用程序的一個獨特關(guān)注點,因為所有相關(guān)的代碼需要動態(tài)下載,并且在瀏覽器解析出必要的JavaScript之前,應(yīng)用程序不會進行交互。對于單頁應(yīng)用程序尤為如此。雖然Vue一直都比較輕量級,但Vue 2的運行時壓縮后的大小也約有23 KB,我們注意到兩個問題:

          首先,并不是每個人都使用框架的所有特性。例如,一個從不使用transition特性的應(yīng)用程序仍然需要付出與使用transition特性相關(guān)的代碼的下載和解析成本。

          第二,隨著我們添加新特性,框架會無限制地增長。當我們權(quán)衡一個新特性添加的利弊時,我們就給了與bundle大小不成比例的權(quán)重。因此,我們傾向于只包含大多數(shù)用戶使用的特性。

          理想情況下,用戶應(yīng)該能夠在構(gòu)建時刪除未使用的框架特性(也稱為“樹抖動-tree shaking”)的代碼,并且只為他們使用的代碼付出成本。這也將使我們能夠在不增加其他用戶的有效負荷成本的情況下,發(fā)布一些用戶認為有用的特性。

          在Vue 3中,我們通過將大多數(shù)全局API和內(nèi)部幫助程序移動到Javascript的module.exports屬性上實現(xiàn)這一點。這允許現(xiàn)代模式下的module bundler能夠靜態(tài)地分析模塊依賴關(guān)系,并刪除與未使用的module.exports屬性相關(guān)的代碼。模板編譯器還生成了對樹抖動友好的代碼,只有在模板中實際使用某個特性時,該代碼才導(dǎo)入該特性的幫助程序。

          框架中有些部分永遠不會被“樹抖動”(這部分的代碼永遠不會從框架中刪除),因為它們對任何類型的應(yīng)用程序都是必不可少的。我們稱這些不可缺少的部分為基線大小。盡管增加了許多新特性,但Vue 3被壓縮后的基線大小約為10 KB,不到Vue 2的一半。


          4、解決規(guī)模性的需求

          我們還希望提高Vue處理大規(guī)模應(yīng)用程序的能力。我們最初的Vue設(shè)計專注于低門檻和溫和的學習曲線。但是隨著Vue被越來越廣泛地采用,我們對包含數(shù)百個模塊并由數(shù)十名開發(fā)人員長期維護的項目的需求了解得更多。對于這種類型的項目,TypeScript之類的類型系統(tǒng)和干凈地組織可重用代碼的能力是至關(guān)重要的,而Vue 2在這些領(lǐng)域的支持并不理想。

          在設(shè)計Vue 3的早期階段,我們試圖通過提供對使用類編寫組件的內(nèi)置支持來改進TypeScript集成。然而挑戰(zhàn)在于,在正式成為JavaScript的一部分之前,我們需要使類可用的許多語言特性(如類字段和裝飾器)仍然是建議的,并且可能會發(fā)生更改。所以,這種方法所涉及的復(fù)雜性和不確定性使我們懷疑添加類API是否真的是合理的,因為除了提供稍好一點的TypeScript集成之外,它沒有提供任何其他特性。

          我們決定研究其他方法來解決規(guī)模性難題。受React鉤子的啟發(fā),我們考慮公開較低級別的響應(yīng)性和組件生命周期API,以實現(xiàn)一種更自由形式的編寫組件邏輯的方法,我們稱之為Composition API。Composition API不需要通過指定一長串選項來定義組件,而是允許用戶像編寫函數(shù)一樣自由地表達、組合和重用有狀態(tài)的組件邏輯,同時提供出色的TypeScript支持。

          我們對這個主意很興奮。盡管Composition API是為解決一類特定的問題而設(shè)計的,但在技術(shù)上只有在編寫組件時才有可能使用它。在提案的初稿中,我們有點超前,并暗示在將來的版本中,我們可能會用Composition API替換現(xiàn)有的Options API,這導(dǎo)致了社區(qū)成員的強烈抵制。這件事給了我們一個寶貴的教訓,讓我們學會清楚地傳達長期計劃和意圖,以及理解用戶的需求。在聽取了我們社區(qū)的反饋后,我們徹底修改這個提議,明確表示Composition API將是Options API的附加和補充。對于這一訂正提案的反饋要積極得多,并收到了許多建設(shè)性的建議。


          5、尋求平衡

          在Vue超過100萬開發(fā)人員的用戶群中,有只掌握HTML/CSS基礎(chǔ)知識的初學者,有從jQuery轉(zhuǎn)移來的專業(yè)人員,有從另一個框架遷移過來的老手,有尋找前端解決方案的后端工程師,以及處理大規(guī)模軟件的軟件架構(gòu)師們。開發(fā)人員知識背景的多樣性導(dǎo)致了用例的多樣性:一些開發(fā)人員可能希望在老舊的應(yīng)用程序上添加交互性,另一些開發(fā)人員可能正在處理一次性的項目,這些項目的周轉(zhuǎn)速度很快,但維護問題有限;而架構(gòu)師們可能不得不在項目的生命周期中處理大型的、多年的項目和面對不斷變化的開發(fā)團隊。

          Vue的設(shè)計不斷地受到這些需求的影響,我們試圖在各種需求之間取得平衡。Vue的口號“漸進式框架”就是對通過這種過程產(chǎn)生的分層API設(shè)計的一種概括。初學者們可以通過使用CDN腳本、基于HTML的模板和直觀的Options API,享受平滑的學習曲線,而專家們則可以使用功能齊全的CLI、渲染函數(shù)和Composition API來處理復(fù)雜的用例。

          為了實現(xiàn)我們的愿景,還有很多工作要做。最重要的工作是更新支持庫、提供文檔和工具,以確保遷移的順利進行。我們將在接下來的幾個月里努力工作,我們迫不及待地想看看Vue社區(qū)會使用Vue 3構(gòu)建出什么。

          英文原文:

          https://increment.com/frontend/making-Vue-3/


          - EOF -

          分享前端好文,點亮?在看?bb9952ae7938fa1136ee9d1fa3a0e1bc.webp

          瀏覽 62
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  东京热小视频 | 亚洲国产精品视频免费看 | 亚洲电影区 | 秋霞福利 | 天堂aaa |