[译] 尤雨溪: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 年。这又一次代表,咱们追求的是稳固性而不是具体的某个日期。虽然工做量很大,但咱们对于新到来的这些特性仍是很是激动!

相关文章
相关标签/搜索