译文:Vue.js 3.0 开发计划

英文原文(需翻墙):

https://medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabfmedium.com


作者尤雨溪,以下是译文


在上周的 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 写一个新的调度器。*

新的代码架构(可能有变)

观察机制

简述:更完备、更精准、更高效,可以对响应式跟踪进行调试,新增了一个创建可观察对象(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 是在什么时候由谁触发的。
很容易知道为什么一个组件会重新渲染

其他的运行时增强

简述:体积更小、速度更快,支持 tree-shaking,支持 fragment 和 portal,支持自定义 render。

  • 体积更小。新的代码库在设计的时候就考虑了 tree-shaking。内置的组件(如 <transition> <keep-alive>)和内置的指令(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:知乎的破二维码识别很烦诶。直接加我微信吧 frank_fang

文章被以下专栏收录