瘋狂的技術宅 前端先鋒 html
每日前端夜話0xE1
每日前端夜話,陪你聊前端。
天天晚上18:00準時推送。
正文共:2484 字
預計閱讀時間:8 分鐘
做者:Filip Rakowski
翻譯:瘋狂的技術宅
來源:vueschool前端
有關即將發佈的 Vue.js 的第 3 個主要版本的信息愈來愈多。經過下面的討論,雖然還不能徹底肯定其全部內容,可是咱們能夠放心地認爲,它將是對當前版本(已經很是出色)的巨大改進。Vue 團隊在改進框架 API 方面作得很是出色。尤雨溪將 Vue 3 的目標描述爲:vue
做爲性能怪胎,在探究某些 API 以前我想先談一談 Vue 3 的性能。react
先從 Vue 3 的捆綁包大小開始。webpack
當前最小化並被壓縮的 Vue 運行時大小約爲 20kB(2.6.10 版爲 22.8kB)。Vue 3捆綁包的大小估計大約會減小一半,即只有大約 10kB!web
諸如更好的模塊化之類的許多其餘優化之上,Vue 3 源代碼將是 tree-shakeable【https://webpack.js.org/guides/tree-shaking/】。這意味着,若是你用不到它的某些功能的話(例如 component 或 v-show 指令),則這些功能將不會包含在你的產品包中。目前不管咱們使用 Vue 核心的什麼功能,這些功能最終都會在咱們的生產代碼中使用,由於 Vue 實例做爲單個對象被導出,而且捆綁程序沒法檢測到該對象的哪些屬性在代碼中使用。算法
1 // Vue 2.x - whole `Vue` object is bundled for production 2import Vue from 'vue' 3 4Vue.nextTick(() => {}) 5const obj = Vue.observable({})
爲了使全局 API 能夠 tree-shake,Vue 團隊決定對其中的大多數 API 經過命名導出,以便捆綁程序能夠檢測和刪除未使用的代碼:性能優化
1 // Vue 3.x - only imported properties are bundled 2import { nextTick, observable } from 'vue' 3 4nextTick(() => {}) 5const obj = observable({})
這是一個重大變化,由於如今經過命名的導出才能使用只能之前的全局 API。這個更改將會影響:app
能夠 tree-shake 的 JavaScript API 不止一個。在後臺,Vue 編譯器(將 Vue 模板轉換爲渲染功能的工具)將檢測模板中使用的指令,並對其進行 tree-shake。例以下面的模板:框架
1<transition> 2 <div v-show="ok">hello</div> 3</transition>
在被 Vue 編譯器處理後,看起來是這樣的:
1import { h, Transition, applyDirectives, vShow } from 'vue' 2 3export function render() { 4 return h(Transition, [ 5 applyDirectives(h('div', 'hello'), this, [vShow, this.ok]) 6 ]) 7}
每一個人都會從全局 API tree-shaking 中受益(尤爲是咱們的用戶),可是我認爲製做小型的輕量級網站並僅使用 Vue 功能子集進行交互的人(最能替代 jQuery 之類的庫)的人會對此最爲重視。
儘管捆綁包的大小可能會嚴重影響應用的加載時間,可是在下載後,它也應該可以快渲染且運行流暢。
Vue 核心團隊很是瞭解這一點,這就是爲何在運行時性能上也有很大改進的緣由。
讓咱們從最具影響力的一種系統開始,它基於 JavaScript Proxies【https://developer.mozilla.org/pl/docs/Web/JavaScript/Referencje/Obiekty/Proxy】。當前的 Vue 響應系統是基於 Object.defineProperty 的,有一些侷限性。最多見並使人沮喪的是 Vue 沒法跟蹤響應對象的屬性添加和刪除【https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats】。爲此咱們須要使用 Vue.set 和 Vue.delete 來保持響應系統的正常運行。經過使用 JS Proxies,咱們終於能夠擺脫這種醜陋的解決方法了。
1// Adding a new property to reacitve object in Vue 2.x 2Vue.set(this.myObject, key, value) 3// Adding a new property to reactive object in Vue 3 4this.myObject[key] = value
代理的真正影響能夠進行更快的組件初始化和修補。根據測試,速度大約快 2 倍!
測試結果
這種改進尤其重要,由於 Vue 必須使用 getters/setters 來遞歸地遍歷全部對象及其屬性,並對其進行轉換。經過使用代理,這個過程就變得容易得多。
值得一提的是,因爲使用了 JS Proxies, Vue 3 將會放棄對 Internet Explorer(而不是Edge)的支持,可是請放心,對於但願支持 IE 的用戶來講,它會保持兼容性。
根據尤雨溪的推文,此功能不會包含在 Vue 3 中。
Vue 3 另外一個使人興奮的性能功能是對時間切片的實驗性支持,可是它不多被說起。
用一個比喻來解釋什麼是時間切片。想象有一條買冰淇淋的隊伍,它很是的長。由於那是鎮上最好的冰淇淋,人們一個接一個的去買。因爲某種緣由,沒有關於可用口味的信息。要獲得這個信息,你須要詢問直接出售冰淇淋的女士。
在這種狀況下,咱們可能最終會獲得 2 條記錄——其中一條給想要購買冰淇淋的人(說服他們耐心等待),另外一條給但願在選擇以前瞭解更多口味信息的人,咱們應該儘快得到這個信息。不幸的是,只有一位女士在賣冰淇淋,她在爲「主」線上的全部客戶提供服務以前不會回答任何問題。
對於還沒有被說服的客戶來講,這並非最好的體驗,大多數人可能會發現這不值得等待。爲了解決這個問題,女士能夠在每 2 至 3 個服務對象中回答一個問題。兩組都應該對此解決方案感到滿意。
這正是 CPU 與 Web 應用一塊兒工做的方式。咱們有一條「主」隊列(稱爲「主線程」),須要完成其全部主要任務(腳本、渲染等),而後才能響應用戶交互。對於某些頁面,這可能會致使很是糟糕的用戶體驗,具體取決於 Vue 組件加載或從新渲染所需的時間。
爲了使其更可靠,最好對此腳本進行評估並「切」成段,在每次執行後查看是否有用戶輸入要處理。這樣,不管須要進行多少次渲染或從新渲染,程序都將保持響應狀態。這就是在 Vue 3 中的工做方式。
這是尤雨溪在 Vue 3 中展現時間分片功能的方式。請注意腳本執行時間軸中的小間隙,能夠在這些間隙中處理用戶輸入。
來自 Vue Mastery 的截圖
工具與開箱即用的性能同等重要。因此咱們能夠在 Vue 3 中看到一個新的生命週期 hook ——renderTriggered。能夠用它來跟蹤和消除沒必要要的組件從新渲染,當把它與時間切片結合使用時,就成了在運行時性能優化中很是強大的武器。
1const Component = { 2 // other properties 3 renderTriggered (event) { 4 console.log(`Re-render of ` + this.$options.name + ` component`, event) 5 } 6}
除了上面在 Vue 3 中看到的內容之外,還有不少東西,可是這些多是影響最大的。許多未說起的改進將會隱藏在 Vue 編譯器生成的代碼中,或者與實現細節和算法綁定在一塊兒
可是,有幾項改進值得一提:
儘管 Vue 已經成爲目前性能最好的框架之一,但咱們仍然將會在第三版中看到重大改進。特別是在捆綁包大小和運行時性能方面。還進行了無數的微優化。我認爲 Vue 3 很是適合現代移動優先和性能導向的 web。
別忘了 Vue 是惟一由社區徹底驅動的主要框架。本文中列出的全部更改都以 RFC 的形式在此處與社區一塊兒討論。你能夠幫助核心團隊,你能夠表達對有效 RFC 的意見,甚至能夠提出本身的改進建議。讓咱們一塊兒使 Vue 更好!