譯文:Vue.js 3.0 開發計劃

方應杭在飢人谷發表於2018-10-01

英文原文(需翻牆)

作者尤雨溪,以下是譯文


在上週的 Vue.js 倫敦會議上我簡短地透露了下個版本的 Vue 的新特性。這篇文章講深入地闡述 Vue 下個版本的計劃。

為什麼要升級到 3.0?

兩年前的今天 Vue 2.0 釋出了(時間過得真快!)。這兩年裡,Vue 更新了五次小版本,這些更新都是向後相容的。Vue 的開發團隊已經了很多不錯的想法,但是為了相容性,我們一直沒有把這些想法加到 2.x 裡。與此同時,JS 的生態系統和語言本身卻在飛速發展。已經有一些非常不錯的工具能提高我們的工作效率,而且一些新的語言特效能更快更好地解決 Vue 2.0 面對的問題。更令人驚喜的是,幾乎所有現代瀏覽器都已經支援 ES2015 了。Vue 3.0 的目的是利用這些新的語言特性,讓 Vue 核心部分變得更輕便、更高效、更強大。

Vue 3.0 目前還處於原型階段,我們已經實現了一個與 Vue 2.x 功能很接近的執行時(runtime)。下文將要說到的很多功能要麼已經被實現了,要麼將要被實現。沒有被實現的特性和還在探索階段的特性將被標記一個 * 號。

更新詳情

上層 API 變化

簡述:除了 render 函式和 scoped-slots 語法之外,所有的 API 都會保持不變或者保持與 Vue 2.0 相容(通過構建工具做到)。

由於這是一個新的版本,所以還是會有一些不相容的地方(breaking change)。不過我們有在認真對待向後相容性,所以我們想要儘早告知這些變化。以下是 API 變化列表:

  • 模板語法 99% 與之前一致。我們會對 scoped-slots 稍加優化,除此之外我們不打算對模板再做什麼變動。
  • 3.0 版本將支援基於 class 的元件。這樣做的目的是讓大家在不依賴轉譯工具、不依賴處於 stage-x 階段的語法特性的情況下,也能愉快地使用 ES2015 語法進行開發。目前的元件選項(options)大部分都會在 class 元件中體現出來。如果你想使用 state-x 階段的語法特性來增強開發體驗,諸如類欄位和修飾器,那麼你可以自己用轉譯工具做到。除此之外,新的 API 將對 TypeScript 保持友好。3.0 版本的程式碼庫將會使用 TypeScript 編寫,並且會提供更好的 TypeScript 支援。(換句話說,你可以使用 TypeScript,也可以不使用 TypeScript,我們不強制。)
  • 2.x 版本里面基於物件的元件依然可以使用。我們會自動將其轉換為一個相應的 class。
  • 混入(Mixin)依然可以使用。*
  • 為了避免 Vue 外掛修改 Vue 的執行時(runtime),頂層 API 有可能會被徹底重寫。新的外掛將被呼叫,且只能作用在一個元件樹上。這樣一來,我們就能更容易地測試依賴於特定外掛的元件了。而且這使得「在同一個頁面上掛在多個 Vue 應用,每個應用裝有不同的外掛且共用同一個 Vue 執行時」成為了可能。
  • 一個普通的函式就能作為一個函式元件。不過如果你想要建立一個非同步元件,就不能這麼簡單了,需要使用一個 API 來建立。
  • 變動最大的要數 render 函式裡的虛擬 DOM 的格式了。我們目前正在向一些重要的庫的作者那裡收集反饋,一旦時機成熟我們就會告知大家更多細節。不過只要你的網站沒有重度依賴手寫的 render 函式(也就是不使用 JSX,直接寫 h),那麼升級到 3.0 將會非常順利。

程式碼架構

簡述:內部模組更解耦,使用了 TypeScript,給 Vue 貢獻程式碼變得更容易。

3.0 版本的程式碼是從零開始的,所以程式碼的架構會更簡明、更具可維護性,我們特意為大家給 Vue 貢獻程式碼提供了便利。為了降低程式碼的複雜度,一些內部功能被放到單獨的 package 裡面了。舉個例子,觀察者(observer)模組連同它的 API 和測試用例,被放在一個單獨的 package 裡了。注意 Vue 的使用者並不需要一一匯入這些單獨的 package,因為 Vue 3.0 將會把這些 package 整合起來。

目前的程式碼庫是用 TypeScript 編寫的。所以想要給 Vue 貢獻程式碼就要提前掌握 TypeScript,但是我們覺得型別資訊和 IDE 提供的便利對於程式碼貢獻者而言利大於弊。

將觀察者和排程器(scheduler)放到單獨的 package 裡也有利於我們去對比不同的實現之間的差異。比如,我們可以為 IE 11 單獨實現一個觀察者,其暴露的 API 可以保持不變。再比如,我們還可以基於 requestIdleCallback 寫一個新的排程器。*

譯文:Vue.js 3.0 開發計劃

新的程式碼架構(可能有變)

觀察機制

簡述:更完備、更精準、更高效,可以對響應式跟蹤進行除錯,新增了一個建立可觀察物件(observable)的 API。

3.0 版本里將有一個基於 Proxy 的觀察者,它會提供全語言覆蓋的響應式跟蹤。相比於 2.x 版本里基於 Object.defineProperty 的觀察者,新的實現更加強大:

  • 可以檢測屬性的新增和刪除
  • 可以檢測陣列索引的變化和 length 的變化
  • 支援 Map、Set、WeakMap 和 WeakSet

新的觀察者還有以下特點:

  • 提供了一個建立可觀察物件的 API。對於中小型應用來說,這個 API 能提供一個輕量、簡單的跨元件狀態管理方案。
  • 預設進行懶觀察(lazy observation)。在 2.x 版本里,不過資料多大,都會在一開始就為其建立觀察者。當資料很大時,這可能會在頁面載入時造成明顯的效能壓力。3.x 版本,只會對「被用於渲染初始可見部分的資料」建立觀察者,而且 3.x 的觀察者更高效。
  • 更精準的變更通知。比例來說:2.x 版本中,你使用 Vue.set 來給物件新增一個屬性時,這個物件的所有 watcher 都會重新執行;3.x 版本中,只有依賴那個屬性的 watcher 才會重新執行。
  • 不可變的可觀察物件(Immutable observable)。我們可以給一個值建立多個不可變的版本,以防有人修改其屬性,必須要在系統在內部臨時將其解鎖時才能修改其屬性。這個機制能夠用於凍結傳給子元件的屬性或者凍結 Vuex 狀態樹之外的狀態變更。
  • 更強大的 debug 能力。我們使用新的 renderTracked 和 renderTriggered 鉤子來精確地查明一個元件的 render 是在什麼時候由誰觸發的。

譯文:Vue.js 3.0 開發計劃

很容易知道為什麼一個元件會重新渲染

其他的執行時增強

簡述:體積更小、速度更快,支援 tree-shaking,支援 fragment 和 portal,支援自定義 render。

  • 體積更小。新的程式碼庫在設計的時候就考慮了 tree-shaking。內建的元件(如 )和內建的指令(v-model)是按需引入的,支援 tree-shaking。新的執行時最小體積將低於 10kb(gzip之後)。除此之外,由於很多特性是支援 tree-shaking 的,所以我們可以提供更多的內建特性,如果你不想用這些特性,你的程式碼體積完全不會增加。
  • 速度更快。我們在進行初步測試時發現所有功能都有 100% 的效能提升,包括虛擬 DOM 的掛載和更新、元件例項的初始化和觀察者的建立。3.0 版本將讓你的應用啟動時間減少一半。
  • 支援 fragment 和 portal。雖然體積變小了,但是 3.0 版本還是帶來了新功能,那就是支援 Fragment(一個元件包含多個根節點)和 Portal(在 DOM 中渲染一個 subtree,而不需要在一個元件中)。
  • 插槽機制增強。所有由編譯產生的插槽現在都是函式,這些函式會在子元件的 render 呼叫時被呼叫。這樣一來,插槽中的依賴會被認為是子元件的依賴而不是父元件的依賴。這意味著:1、當插槽內容變化時,只有子元件重新渲染;2、當父元件重新渲染時,如果插槽內容沒有變化,子元件就不需要重新渲染。這個特性提供了更精確的元件樹層面上的變更檢測,所以會減少很多無用的渲染。
  • 自定義 render。我們會提供一個 API 用來建立自定義的 render,因此你不需要為了自定義一些功能而 fork Vue 的程式碼。這個特性給 Weex 和 NativeScript Vue 這樣的專案提供了很多便利。

編譯器增強

簡述:編譯出的內容對 tree-shaking 友好,更多 AOT 優化,更好的錯誤提示,對 source map 的支援更好。

  • 為了輸出對 tree-shaking 友好的程式碼,模板中如果用到了一些可選特性,那麼生成的程式碼中將使用 ES 模組語法來 import 這些特性。因此沒有用到的可選特性就不會出現在最終程式碼中。
  • 由於我們對虛擬 DOM 進行了優化,所以有了更高效的編譯時優化,比如靜態樹提升、靜態屬性提升、為執行時新增編譯提示資訊以減少子節點正常化(children normalization),VNode 建立的快速路徑等。
  • 我們計劃重寫解析器(parser),以在模板編譯錯誤提示中新增位置資訊。這也會使得 Vue 支援模板的 source map。新的解析器可以提供給第三方工具使用,比如 eslint-plugin-vue 和 IDE。

支援 IE 11*

簡述:Vue 3.0 支援 IE 11,但是需要單獨構建,而且其觀察者的實現和 Vue 2.x 一樣。

新的程式碼庫目前只支援現代瀏覽器(evergreen),且預設使用 ES2015 語法。但是啊,我們知道很多開發者還是需要相容 IE 11 一段時間。大部分 ES 2015 語法都可以通過轉譯和 polyfill 執行在 IE 11 上,除了 Proxy。我們的計劃是用 Object.defineProperty 單獨給 IE 11 實現一個提供相同 API 的觀察者。Vue 3.x 會基於這個觀察者再釋出一個版本。但是,這個版本跟 Vue 2.x 一樣存在一些限制,所以跟 3.x 並不完全相容。我們知道這會給一些庫的開發者帶來不便,因為庫的開發者需要清楚這兩種不同的構建版本,所以我們保證屆時會給大家提供清晰的文件。

如何達成 Vue 3.0

首先,儘管我們今天就宣佈了 Vue 3.0 的計劃,但是我們並沒有一個明確的日程。為了順利完成 Vue 3.0 的開發,我們會按如下步驟來做:

1、對執行時的原型做內部討論

目前我們處於這個階段。我們已經做出了一個可以使用的執行時原型,包括新的觀察者、新的虛擬 DOM 和新的元件實現。我們已經邀請了一些有影響力的專案的開發者來提供反饋,希望新的變更對他們來說體驗良好。我們想確保在 3.0 版本釋出的時候,JS 生態中那些重要的庫都已經做好了準備,這樣一來大家就可以愉快地把自己的專案升級到 3.0 了。

2、 通過 RFC 公開收集反饋

一旦我們對新的設計有了足夠的自信,對於每一個 breaking change 我們都會開啟一個專門的 RFC issue,內容包括:

  • 變更範圍
  • 變更理由:我們有什麼收益,我們做出了哪些妥協
  • 升級方法:它是否可以通過一個可移除的相容層或者程式碼補丁做到完全向後相容。

我們將參與社群的討論,以便我們更好地達成以上目標。

3、為 2.x 版本引入新的特性

我們不會棄 2.x 版本不顧的!實際上,我們打算在 2.x 版本中引導開發者逐漸瞭解這些新特性。我們會逐漸向 2.x 版本引入一些新 API,之後的 2.x 版本將允許開發者嘗試接入基於 Proxy 的觀察者。

最近的一個 2.x 版本將會變為長期支援版本(LTS),在接下來的一年半里我們會繼續解決這個版本的 bug 和安全性問題。

4、內測(Alpha)階段

然後,我們將會完成 3.0 版本的編譯器和服務端渲染,併發布內測版本,主要是在小型的新應用上面測試 Vue 3.0 的穩定性。

5、公測(Beta)階段

在公測階段,我們的主要目的是幫助 Vue 周邊庫的升級,比如 Vue Router、Vuex、Vue CLI 和 Vue DevTools,以確保它們能完全支援 Vue 3.0。我們也會進一步幫助社群中其他的庫升級。

6、釋出候選(RC)階段

一旦我們認為 API 和程式碼庫已經足夠穩定了,我們就會凍結 API 並進入釋出候選階段。在這個階段我們會考慮推出一個相容版本:一個支援 2.x 版本的 API 的 3.0 版本。如果你的應用使用的是 2.x 版本的 API,這個版本就會給出警告提示,你可以在編譯的時候關閉這個提示。這個相容版本可以作為你的升級嚮導。

7、IE 11 版本

最後我們會推出相容 IE 11 的 3.0 版本。

8、最終釋出

說實話我們也不知道什麼時候最終釋出,可能是 2019 年。再次宣告,比起確定一個最終釋出日期,我們更在意 3.0 版本的健壯性和穩定性。我們還有很多工作要做,不過我們對 Vue 3.0 充滿了期待。


正文結束。

如果你在學習 Vue,可以加入飢人谷的 Vue 交流群 4:

譯文:Vue.js 3.0 開發計劃

相關文章