[譯] 尤雨溪:Vue 3.0 計劃

原文Plans for the Next Iteration of Vue.js
做者Evan You 發表時間:Sep 30, 2018
譯者:西樓聽雨 發表時間: 2018/10/5 (轉載請註明出處)javascript


展開原文 Last week at Vue.js London I gave a brief sneak peek of what’s coming in the next major version of Vue. This post provides an in-depth overview of the plan.

上週,在Vue.js 倫敦會議上,我對 Vue 的下一個主版本將帶來的東西作了一個粗略的介紹。這篇貼文則將提供一份關於這個計劃的詳細介紹。vue

爲何要出一個新的主版本?

展開原文 Vue 2.0 was released exactly two years ago (how time flies!). During this period, the core has remained backwards compatible with five minor releases. We’ve accumulated a number of ideas that would bring improvements, but they were held off because they would result in breaking changes. At the same time, the JavaScript ecosystem and the language itself has been evolving rapidly. There are greatly improved tools that could enhance our workflow, and many new language features that could unlock simpler, more complete, and more efficient solutions to the problems Vue is trying to solve. What’s more exciting is that we are seeing ES2015 support becoming a baseline for all major evergreen browsers. Vue 3.0 aims to leverage these new language features to make Vue core smaller, faster, and more powerful. Vue 3.0 is currently in prototyping phase, and we have already implemented a runtime close to feature-parity with 2.x. Many of the items listed below are either already implemented, or confirmed to be feasible. Ones that are not yet implemented or still in exploration phase are marked with a *.

Vue 2.0 已經發布有整整兩年了(時間過得可真快啊!)。在這段時期,Vue 發佈了 5 個保持內核後向兼容的次要版本;咱們積累了許多能夠帶來各類提高的點子,可是這些點子一直被擱置着,由於他們會帶來打破兼容性的變更。與此同時,JavaScript 的生態系統及其自己也在急速地發展。許多工具的提高改善了咱們的工做流,許多新語言特性給 Vue 一直在嘗試解決的問題解鎖了一些更簡單、更全面、更高效的解決方案。更使人興奮的是,咱們看到了對 ES2015 的支持已經成爲全部主流瀏覽器的基準。而 Vue 3.0 的目的就是藉助這些新語言特性來讓 Vue 的內核變得更小、更快、更強大。java

Vue 3.0 已經在原型設計階段了,並且咱們已經實現了一個與 2.0 的特性近乎相等的運行時了。下文中列出的許多條目,要麼已經實現了,要麼已經確承認實現。那些還未實現或者仍在探索階段的條目會用一個「*」標記node

細節

高層 API 變更

一句話介紹:除渲染函數 API 和 scoped-slot 語法以外,其他均保持不變或者將經過另外構建一個兼容包來兼容 2.x。react

展開原文 Since it’s a new major, there is going to be some breaking changes. However, we take backwards compatibility seriously, so we want to start communicating these changes as soon as possible. Here’s the currently planned public API changes:
  • Template syntax will remain 99% the same. There may be small tweaks in scoped slots syntax, but other than that we have no plans to change anything else for templates.
  • 3.0 will support class-based components natively, with the aim to provide an API that is pleasant to use in native ES2015 without requiring any transpilation or stage-x features. Most current options will have a reasonable mapping in the class-based API. Stage-x features such as class fields and decorators can still be used optionally to enhance the authoring experience. In addition, the API is designed with TypeScript type inference in mind. The 3.x codebase will itself be written in TypeScript, and providing improved TypeScript support. (That said, usage of TypeScript in an application is still entirely optional.)
  • The 2.x object-based component format will still be supported by internally transforming the object to a corresponding class. Mixins will still be supported. *
  • Top level APIs will likely receive an overhaul to avoid globally mutating the Vue runtime when installing plugins. Instead, plugins will be applied and scoped to a component tree. This will make it easier to test components that rely on specific plugins, and also make it possible to mount multiple Vue applications on the same page with different plugins, but using the same Vue runtime. *
  • Functional components can finally be plain functions —however, async components will now need to be explicitly created via a helper function.
  • The part that will receive the most changes is the Virtual DOM format used in render functions. We are currently collecting feedback from major library authors and will be sharing more details as we are more confident of the changes, but as long as you don’t heavily rely on hand-written (non-JSX) render functions in your app, upgrading should be a reasonably straightforward process.

因爲此次是一個新的主版本,因此會存在一些打破兼容的變更。不過,咱們對後向兼容是很是重視的,因此咱們但願可以儘快開始跟你們溝通這些變更。下面就是當前咱們計劃的公共 API 變更:ios

  • 模板語法的 99% 將保持不變。除了 scoped slot 語法可能會有一些微調以外,咱們尚未任何其餘針對模板的變更計劃。
  • 3.0 版本將原生地支持基於 class 的組件,並且無需藉助任何編譯及各類 stage 階段的特性,以此提供良好的編寫體驗。許多現有的 (組件) 配置項將有對應的合理的 class 版本的 API。各類 stage 階段的特性,如 class 的靜態字段和裝飾器 (decorator) 等仍然能夠選擇性地使用,以此加強編寫體驗。另外,總體的 API 在設計時也將考慮 TypeScript 的類型推斷特性。3.x 的代碼庫自己將用 TypeScript 來編寫,並提供加強的 TypeScript 支持。(就是說,TypeScript 的使用與否仍然是總體可選的)
  • 2.x 系列的基於對象的組件格式仍將受支持,不過會在內部將其轉換爲一個相應的 class。
  • 仍然支持 Mixins。*
  • 爲了不在安裝插件時形成對 Vue 的運行時的修改,頂層 API 可能會作一個大的翻修。到時,插件的做用域將只侷限到具體的一個組件樹,使得對那些依賴於某些具體插件的組件的測試變得容易,也會使得在同一個頁面中掛載多個使用不一樣插件——但使用同一個 Vue 運行時——的 Vue 應用變爲可能。*
  • 函數式組件將支持純函數的書寫形式——不過,這樣的話異步組件就須要經過一個輔助性函數來顯式地建立了。
  • 變更最大的部分將是渲染函數 (render) 中的虛擬DOM的格式。咱們如今正在收集主流的第三方庫的做者們的反饋,在對這些變更有了更多的信心以後,咱們還會將更多的細節曝光;雖然變更較大,可是隻要你沒在你的應用中重度使用手寫的渲染函數 (不是指 JSX),那麼變更以後的升級應該會比較容易。

代碼架構

一句話介紹:更優良的內部模塊解耦;TypeScript;更易於貢獻的代碼庫。git

展開原文 We are re-writing 3.0 from the ground up for a cleaner and more maintainable architecture, in particular trying to make it easier to contribute to. We are breaking some internal functionalities into individual packages in order to isolate the scope of complexity. For example, the observer module will become its own package, with its own public API and tests. Note this does not affect framework-level API— you will not have to manually import individual bits from multiple packages in order to use Vue. Instead, the final Vue package is assembled using these internal packages.

The codebase is also now written in TypeScript. Although this will make proficiency in TypeScript a pre-requisite for contributing to the new codebase, we believe the type information and IDE support will actually make it easier for a new contributor to make meaningful contributions.github

Decoupling the observer and scheduler into separate packages also allows us to easily experiment with alternative implementations of these parts. For example, we can implement an IE11 compatible observer implementation with the same API, or an alternative scheduler that leverages requestIdleCallback to yield to the browser during long updates.*web

在從零開始編寫 3.0 之初,「達到更加清晰和更易維護的架構,特別是爲了讓代碼的貢獻變得容易」就是咱們的目標。爲了對複雜性進行隔離,咱們將一些內部功能拆分爲了多個單獨的包。例如,observer 模塊將成爲一個單獨的包,擁有本身對外的 API 和本身的測試用例;不過請注意,這不會對框架級的 API 形成影響——你不須要另外手動從多個包裏導入許多小件小件的模塊就可使用 Vue,相反 Vue 的最終包會事先裝配好這些內部包。vuex

另外,代碼庫如今改成了用 TypeScript 編寫;雖然這會使得「熟練TypeScript」成爲對新代碼庫進行貢獻的一個前置要求,不過咱們相信有類型信息配合 IDE 的支持,對於一個新的貢獻者來講,要作出有意義的貢獻,實際上反而會更加容易。

將 observer 和 scheduler 解耦爲分開的兩個包後,咱們還能夠拿一些替代的實現對這兩個包進行置換試驗。例如,咱們能夠實現一個兼容 IE十一、API 也相同的 observer;或者實現另一種利用 requestIdleCallback 來在長耗時的更新中產出工做成果到瀏覽器的 scheduler。

img

監測機制

一句話介紹:更加全面、精準、高效;更具可調試性的響應跟蹤;以及可用來建立響應式對象的 API。

展開原文 3.0 will ship with a Proxy-based observer implementation that provides reactivity tracking with full language coverage. This eliminates a number of limitations of Vue 2’s current implementation based on Object.defineProperty :

3.0 將帶來一個基於 Proxy 的 observer 實現,它能夠提供覆蓋語言 (JavaScript——譯註) 全範圍的響應式能力,消除了當前 Vue 2 系列中基於 Object.defineProperty 所存在的一些侷限,如:

  • 對屬性的添加、刪除動做的監測
  • 對數組基於下標的修改、對於 .length 修改的監測
  • 對 Map、Set、WeakMap 和 WeakSet 的支持
展開原文 - Exposed API for creating observables. This offers a light-weight, dead simple cross-component state management solution for small to medium scale scenarios. - Lazy observation by default. In 2.x, any reactive data, regardless of how big it is, will be observed on startup. This can cause a noticeable overhead on app startup if your dataset is huge. In 3.x, only data used to render the initially visible part of your app will need to be observed, not to mention the observation itself is also much faster. - More precise change notification. An example: in 2.x, force adding a new property using Vue.set will cause any watcher that depends on the object to re-evaluate. In 3.x, only watchers that relies on that specific property will be notified. - Immutable observables: we can create 「immutable」 versions of a value that prevents mutations even on nested properties, except when the system temporarily unlocks it internally. This mechanism can be used to freeze passed-down props or Vuex state trees outside mutations. Better debugging capabilities: we can precisely trace when and why a component re-render is tracked or triggered using the new renderTracked and renderTriggered hooks:

另外這個新的 observer 還有如下特性:

  • 公開的用於建立 observable (即響應式對象——譯註) 的 API。這爲小型到中型的應用提供了一種輕量級的、極其簡單的跨組件狀態管理解決方案。(譯註:在這以前咱們能夠經過另外 new Vue({data : {...}}) 來建立這裏所謂的 observable;另外,其實 vuex 內部也是用這種方式來實現的)
  • 默認爲惰性監測(Lazy Observation)。在 2.x 版本中,任何響應式數據,無論它的大小如何,都會在啓動的時候被監測。若是你的數據量很大的話,在應用啓動的時候,這就可能形成可觀的性能消耗。而在 3.x 版本中,只有應用的初始可見部分所用到的數據會被監測,更不用說這種監測方案自己其實也是更加快的。
  • 更精準的變更通知。舉個例子:在 2.x 系列中,經過 Vue.set 強制添加一個新的屬性,將致使全部依賴於這個對象的 watch 函數都會被執行一次;而在 3.x 中,只有依賴於這個具體屬性的 watch 函數會被通知到。
  • 不可變監測對象(Immutable observable):咱們能夠建立一個對象的「不可變」版本,以此來阻止對他的修改——包括他的嵌套屬性,除非系統內部臨時解除了這個限制。這種機制能夠用來凍結傳遞到組件屬性上的對象和處在 mutation 範圍外的 Vuex 狀態樹。
  • 更良好的可調試能力:經過使用新增的 renderTrackedrenderTriggered 鉤子,咱們能夠精確地追蹤到一個組件發生重渲染的觸發時機和完成時機,及其緣由。

img

其餘的運行時提高

一句話簡介:更小巧,更快速;支持搖樹優化;支持 Fragments 和跨組件渲染;支持自定義渲染器。

展開原文 - Smaller: the new codebase is designed from the ground up to be tree-shaking friendly. Features such as built-in components (, ) and directive runtime helpers (v-model) are now imported on-demand and tree-shakable. The constant baseline size for the new runtime is <10kb gzipped. In addition, features being tree-shakable also allows us to offer more built-in features down the road without incurring payload penalties for users that don’t use them. - Faster: on preliminary benchmarks, we are seeing up to 100% performance improvement across the board, including raw Virtual DOM mounting & patching (we learned quite a few tricks from Inferno, the fastest Virtual DOM implementation out there), component instance initialization and data observation. 3.0 will shave off half the time spent in JavaScript when your app boots up. Fragments & Portals: despite the size reduction, 3.0 comes with built-in support for Fragments (component returning multiple root nodes) and Portals (rendering a sub-tree in another part of the DOM, instead of inside the component). - Improved slots mechanism: All compiler-generated slots are now functions and invoked during the child component’s render call. This ensures dependencies in slots are collected as dependencies for the child instead of the parent. This means that: 1. when slot content changes, only the child re-renders; 2. when the parent re-renders, the child does not have to if its slot content did not change. This change offers even more precise change detection at the component tree level, so even fewer useless re-renders! - Custom Renderer API: a first-class API for creating custom renderers will be available, and no longer requires forking the Vue codebase with custom modifications. This will make it much easier for render-to-native projects like Weex and NativeScript Vue to stay up-to-date with upstream changes. It would also make it trivially easy to create custom renderers for various other purposes.
  • 更小巧:這份新的代碼庫在設計之初就考慮到了對「搖樹優化 (tree-shaking)」的友好。那些如內置組件 (<transition><keep-alive>) 、運行時工具性指令(v-model)等特性將變爲按需導入,因此也是「可搖樹的」。對於這個新的運行時,它的大小將永遠保持在 10kb 之下。另外,使這些特性變爲「可搖樹的」後,咱們就能夠提供更多的內置特性,同時還不會增長網絡負載——若是沒使用到這些特性的話。

    譯註:搖樹優化,是一種在打包時去除沒用到的代碼的優化手段,谷歌有一篇教程能夠了解下: Reduce JavaScript Payloads with Tree Shaking

  • 更快:在前期的基準測試中,咱們看到總體性能有了一倍的提高,包括虛擬DOM的掛載和打補丁(patching,指更新——譯註) 的速度(咱們從 Inferno 那裏學了好些個技巧過來——Inferno 是目前速度最快的虛擬DOM實現),以及組件實例化速度和數據監測的性能。在 3.0 中,你應用的啓動時間將縮減一半。

  • 支持 Fragments 和 Portal:雖然體積更小了,但 3.0 還將內置對 Fragments (即容許組件擁有多個根節點) 和 Portal (即容許在 DOM 的其餘位置進行渲染,而不是組件內部) 的支持。

    譯註:關於 Portal ,你能夠將其理解爲跨組件渲染或者異地渲染,vue-portal 是一個第三方實現,能夠了解一下;Fragments 特性也有一個第三方庫,但譯者認爲這個庫的內部實現不夠完善,叫作 vue-fragments,感興趣能夠了解一下。

  • 加強的 slot 機制:全部由編譯器生成的 slot 都將是函數形式,而且在子組件的 render 函數被調用過程當中才被調用 (譯註:如今只有 scoped slot 纔是函數形式,其渲染的時機也是在父組件的渲染進行時)。這使得 slot 中的依賴項 (即數據——譯註) 將被做爲子組件的依賴項,而不是如今的父組件;從而意味着:1)當 slot 的內容發生變更時,只有子組件會被從新渲染;2)當父組件從新渲染時,若是子組件的內容未發生變更,子組件就不必從新渲染。這種機制的改變,能夠提供更精確的變更探測,也就能夠消除不必的重渲染。

  • 支持自定義渲染器 (Renderer):這個 API 能夠用來建立自定義的渲染器,它將做爲「一等公民」出現,到時再也不須要 fork 一份 Vue 的代碼來經過修改實現自定義。這個 API 的到來,將使得那些如 Weex 和 NativeScript 的「渲染爲原生應用」的項目保持與 Vue 的同步更新變得更加容易。除此以外,還將使得那些爲了各類用途而建立自定義渲染器變得極其容易。

編譯器相關的提高 *

一句話介紹:「搖樹友好」的輸出;更多的 AOT 優化;更良好的解析錯誤;支持 source map。

展開原文 - When targeting tree-shaking-capable bundlers, templates that make use of optional features will generate code that imports those features using ES modules syntax. Unused optional features are thus dropped from the final bundle. - Due to improvements in the new Virtual DOM implementation, we are also able to perform more effective compile-time optimizations such as static tree hoisting, static props hoisting, compiler-hints for runtime to skip children normalization, VNode creation fast paths, etc… - We plan to rewrite the parser to provide location information in template compilation errors. This should also lead to template source map support, and the new parser can serve as the foundation for 3rd party tooling integration, such as eslint-plugin-vue and IDE language services.
  • 若是採用的是支持「搖樹優化」的打包器,模板中使用到的那些可選特性,在生成的代碼中將經過 ES 的模塊語法導入;而在打包後的文件中,那些沒用到的可選特性就會被「搖掉」。
  • 因爲新的虛擬 DOM 實現所帶來的提高,咱們能夠執行一些更加高效的編譯耗時優化,如靜態樹提高(static tree hoisting)、靜態屬性提高(static props hoisting);以及爲運行時提供一些來自編譯器的提示,以此避開子組件的規範過程 (children normalization);提供 VNode 快速建立路徑; 等等。
  • 咱們計劃對解析器進行重寫,以便在對模板進行編譯發生錯誤時,能夠提供錯誤發生的位置信息;除此以外還能夠帶來對模板的 source map 支持;還能夠支持第三方工具如 eslint-plugin-vue 和 IDE 的語言服務 (language services) 特性。

兼容 IE 11 *

一句話介紹:IE 11 將受到支持,但將會是另外構建一個版本 (build) 的形式支持,不過這個版本會存在與 Vue 2.x 響應式機制所存在的一樣的侷限。

展開原文 The new codebase currently targets evergreen browsers only and assumes baseline native ES2015 support. But alas, we know a lot of our users still need to support IE11 for the foreseeable future. Most of the ES2015 features used can be transpiled / polyfilled for IE11, with the exception for Proxies. Our plan is to implement an alternative observer with the same API, but using the good old ES5 Object.defineProperty API. A separate build of Vue 3.x will be distributed using this observer implementation. However, this build will be subject to the same change detection caveats of Vue 2.x and thus not fully compatible with the 「modern」 build of 3.x. We are aware that this imposes some inconvenience for library authors as they will need to be aware of compatibility for two different builds, but we will make sure to provide clear guidelines on this when we reach that stage.

新的代碼庫目前只針對主流瀏覽器,並且咱們假定他們都支持 ES2015。可是,哎,咱們也知道在可預見的將來還有不少用戶仍然須要支持 IE11。除了 Proxy 外,大多數 ES2015 的特性均可以用轉譯或者墊片的方式在 IE11 中使用。咱們的計劃是另外單獨實現一個具備一樣 API 的替代性 observer,不過是基於老式的 Object.defineProperty API;而後再經過單獨構建一個使用這個實現的 Vue 3.x 版本 (build) 進行發佈,不過這個單獨的版本仍是會有 Vue 2.x 在變更探測方面所存在的問題,因此它其實並非一個徹底兼容 3.x 的一個版本。咱們也意識到這會給第三方庫的做者們帶來某些不便,由於他們須要考慮兩個不一樣版本之間的兼容性問題,不過當咱們真的推動到那個階段時,那時咱們確定會確保提供一份清晰的指導 (關於如何處理這個問題的指導——譯註) 。

咱們將如何達成目標

雖然咱們是在今天宣佈的,不過咱們尚未一個肯定的時間表,目前咱們有的是實現這些目標的步驟:

1. 徵集運行時原型的反饋

展開原文 This is the phase we are in right now. Currently, we already have a working runtime prototype that includes the new observer, Virtual DOM and component implementation. We have invited a group of authors of influential community projects to provide feedback for the internal changes, and would like to make sure they are comfortable with the changes before moving forward. We want to ensure that important libraries in the ecosystem will be ready at the same time when we release 3.0, so that users relying on those projects can upgrade easily.

這也是咱們當前所處的階段。目前,咱們已經有了一個可以運行的運行時原型,它包括一個新的 observer、新的虛擬 DOM和一個新的組件實現。咱們邀請了一隊流行的社區項目的做者,收集他們對這些底層變更的反饋,但願在繼續推動前他們對這些變更可以輕鬆適應。咱們但願在 3.0 發佈之時,Vue 生態中的這些重點的三方庫也已經同步作好了準備,以便依賴於這些項目的用戶能夠輕鬆地升級。

2. 經過 RFC 徵集公衆反饋

展開原文 Once we gain a certain level of confidence in the new design, for each breaking change we will be opening a dedicated RFC issue which includes:

Scope of the change;

  • Reasoning behind the change: what do we gain, and what tradeoffs are being made;
  • Upgrade path: can it be introduced in a completely backwards-compatible fashion, via a removable compatibility layer, or via codemods?
  • We will anticipate public feedback from the wider community to help us consolidate these ideas.

在咱們對這份新的設計有了某種程度的信心以後,咱們會爲每一項非兼容性變更設立一個專門的 RFC 頻道,主要將包含如下信息:

  • 該項變更的影響範圍;
  • 該項變更的得失考量:咱們會獲得什麼,又有哪些代價。
  • 該項變更的升級途徑:是採用徹底後向兼容的形式,仍是經過植入一個可移除的兼容性層,或者是經過修改代碼來升級?

3. 在 2.x 和 2.x-next 中引入兼容性特性

展開原文 We are not forgetting about 2.x! In fact, we plan to use 2.x to progressively accustom users to the new changes. We will be gradually introducing confirmed API changes into 2.x via opt-in adaptors, and 2.x-next will allow users to try out the new Proxy-based observer.

The last minor release in 2.x will become LTS and continue to receive bug and security fixes for 18 months when 3.0 is released.

咱們不會忘記 2.x!咱們計劃經過 2.x 來讓用戶漸進式地適應這些新的變更。咱們會經過一些適配器逐步地往 2.x 中引入驗證過得 API 變更;另外,2.x-next 版本還將容許用戶嘗試新的基於 Proxy 的 observer。

最後一次發佈的 2.x 的次版本將成爲 LTS 版本,在 3.0 發佈後的 18 個月內將繼續接收到 bug 和 安全性修復。

4. Alpha 階段

展開原文 Next, we will finish up the compiler and server-side rendering parts of 3.0 and start making alpha releases. These will mostly be for stability testing purposes in small greenfield apps.

在接下來的這個階段,咱們將完成 3.0 的編譯器和服務端渲染的部分,並開始製做 alpha 版本。這些工做的主要目的是爲了在一些小的應用中進行穩定性測試。

5. Beta 階段

展開原文 During beta phase, our main goal is updating support libraries and tools like Vue Router, Vuex, Vue CLI, Vue DevTools and make sure they work smoothly with the new core. We will also be working with major library authors from the community to help them get ready for 3.0.

在 beta 階段,咱們的主要目標是更新相關的支持庫,如 Vue Router、Vuex、Vue CLI、Vue DevTools,以此確保他們可以流暢地與這個新的內核協同。另外咱們還會經過社區來幫助第三方庫的開發者們,與他們一塊兒工做,迎接 3.0 的到來。

6. RC 階段

展開原文 Once we consider the API and codebase stable, we will enter RC phase with API freeze. During this phase we will also work on a 「compat build」: a build of 3.0 that includes compatibility layers for 2.x API. This build will also ship with a flag you can turn on to emit deprecation warnings for 2.x API usage in your app. The compat build can be used as a guide to upgrade your app to 3.0.

當咱們認爲各項 API 和代碼庫已經穩定時,咱們將進入 RC 階段,同時 API 也就固定下來了。在這個階段,咱們還將構建一個「兼容版本」(compat build) :一種包含了兼容 2.x API 的兼容性層的 3.0 版本,它還會提供一個標記,你能夠打開這個標記,以此讓其在你應用使用了 2.x API 的地方發出 API 已通過時的警告提示;所以這個「兼容版本」也能夠用來在升級 3.0 時提供指南 (即給出那些地方須要升級——譯註)。

7. 構建 IE 11 版本

The last task before the final release will be the IE11 compatibility build as mentioned above.

最終發佈前的最後一項任務就是前面提到的那個兼容 IE 11 的版本。

8. 最終發佈

展開原文 In all honesty, we don’t know when this will happen yet, but likely in 2019. Again, we care more about shipping something that is solid and stable rather than hitting specific dates. There is a lot of work to be done, but we are excited for what’s coming next!

坦率講,咱們還不知道什麼時候能推動到這個階段,不過多是在 2019 年。這又一次代表,咱們追求的是穩固性而不是具體的某個日期。雖然工做量很大,但咱們對於新到來的這些特性仍是很是激動!

相關文章
相關標籤/搜索