我们倾向于听到越来越多有关即将发布的Vue.js的第3个主要版本的信息。通过下面的讨论,虽然还不能确定所有内容,但是我们可以放心地认为,它将是对当前版本(已经非常出色)的巨大改进。Vue团队在改进框架API方面做得非常出色。Evan You将Vue 3的目标描述为:
- 让它更快
- 让它更小
- 使它更易于维护
- 使其更容易瞄准本土
- 让您的生活更轻松
通过查看RFC并进行交谈,我确信上述所有目标都可以毫无问题地实现。在本文中,我想引导您完成一些对我来说最有趣的更改,这些更改就其影响和可能性而言。
性能优化
在探讨某些API之前,作为性能极客,我想谈一谈Vue 3的性能。还有很多要讨论的问题!我们几乎可以在每个表面上找到明显的改进!
让我们从Vue 3的捆绑包大小开始。
当前最小化和压缩的Vue运行时权重约为20kB(当前2.6.10版本为22.8kB)。Vue 3捆绑包估计重约一半,因此只有〜10kB!
全球API摇树
诸如更好的模块化之类的许多其他优化之上,Vue 3源代码将是可tree-shakeable。这意味着,如果您不使用其某些功能(例如<keep-alive>
组件或v-show
指令),它们将不会包含在您的产品包中。当前,无论我们从Vue核心使用什么功能,它们最终都会出现在生产代码中,因为Vue实例作为单个对象导出,并且捆绑程序无法检测到该对象的哪些属性在代码中使用。
// Vue 2.x - whole `Vue` object is bundled for production
import Vue from 'vue'
Vue.nextTick(() => {})
const obj = Vue.observable({})
为了使全局API可以摇树,Vue团队决定通过命名导出导入其中的大多数,以便捆绑程序可以检测和删除未使用的代码:
// Vue 3.x - only imported properties are bundled
import { nextTick, observable } from 'vue'
nextTick(() => {})
const obj = observable({})
这是一个重大变化,因为以前的全局API现在仅可通过命名的导出使用。此更改影响:
Vue.nextTick
Vue.observable
Vue.version
-
Vue.compile
(仅完整版本) -
Vue.set
(仅在2.x兼容版本中,您很快会找到原因) -
Vue.delete
(同上)
我们需要一段时间才能完全受益于此功能,因为它需要在生态系统中采用。Vue团队将发布兼容性版本,因此我们应该能够使用也使用旧API的插件,但会降低性能。
可以摇树的JavaScript API不止一个。在后台,Vue编译器(将Vue模板转换为渲染功能的工具)将检测模板中使用的指令,并对其进行树状摇动。例如下面的模板:
<transition>
<div v-show="ok">hello</div>
</transition>
在被Vue编译器处理后,看起来或多或少是这样的:
import { h, Transition, applyDirectives, vShow } from 'vue'
export function render() {
return h(Transition, [
applyDirectives(h('div', 'hello'), this, [vShow, this.ok])
])
}
每个人都会从全局APItree-shaking
中受益(尤其是我们的用户),但是我认为制作小型,轻量级网站并仅使用Vue功能子集进行交互的人(最能替代jQuery之类的库)的人会最看重它。
基于代理的反应性
捆绑包的大小会显着影响您的应用加载时间,但是下载后,捆绑包的大小也应能够快速呈现且运行流畅。
Vue核心团队非常了解这一点,这就是为什么我们在运行时性能上也有很大改进的原因。
让我们从基于JavaScript Proxies的最具影响力的新反应系统之一开始。当前的Vue反应系统是基于的Object.defineProperty
,它有一些局限性。最常见和令人沮丧的一个事实是Vue无法跟踪反应对象的属性添加/删除。为此,我们需要使用Vue.set
并Vue.delete
保持反应系统正常运行。有了JS Proxies,我们终于可以摆脱这种丑陋的解决方法。
// Adding a new property to reacitve object in Vue 2.x
Vue.set(this.myObject, key, value)
// Adding a new property to reactive object in Vue 3
this.myObject[key] = value
代理的真正影响可以从更快的组件初始化和修补中看出。根据测试,速度大约快2倍!

由于以下事实,这种改进的原因尤为重要,那就是Vue必须使用吸气剂/设置剂来递归地遍历所有对象及其属性并对其进行转换。使用代理,此过程变得容易得多。
重要的是要提到,通过使用JS Proxies Vue 3,将放弃对Internet Explorer(不是Edge)的支持,但是请不要担心-对于希望支持IE的用户,将有一个兼容版本。
时间分片
根据Evan You的推文更新此功能不会包含在Vue 3中。
Vue 3的另一个真正令人兴奋但很少提及的性能功能是对时间切片的实验支持。
我将用一个隐喻来解释什么是时间切片。我想让你想象一条冰淇淋生产线。很长的一个,因为那是镇上最好的冰淇淋。提供一个人之后,就会出现另一个人,依次类推。等等。由于某种原因,没有关于可用口味的信息。要获取此信息,您需要询问直接出售冰淇淋的女士。
在这种情况下,我们可能最终会得到2条记录-其中一条给说服他们想要购买冰淇淋的人(耐心等待),另一条给希望在选择风味之前了解更多口味信息的人。不是。最新的应该尽快获得此信息。不幸的是,只有一位女士在卖冰淇淋,在为“主”线上的所有客户服务之前,她不会回答任何问题。
对于尚未被说服的客户来说,这并不是最好的体验,他们中的大多数人可能会发现不值得等待。为了解决这个问题,女士可以在每2至3个服务对象中回答一个问题。两组都应该对此解决方案感到满意。
这正是CPU与Web应用程序一起工作的方式。我们有一条“主”行(称为“主线程”),需要完成其所有主要任务(脚本,渲染等),然后才能响应用户交互。对于某些页面,这可能会导致非常糟糕的用户体验,具体取决于Vue组件加载或重新渲染所需的时间。
为了使其更可靠,最好将此脚本评估“切割”成碎片,然后查看每个脚本评估之后是否有要处理的用户输入。这样,无论需要进行多少次渲染或重新渲染,应用程序都将保持响应状态。这就是在Vue 3中的工作方式。
这是Evan在Vue 3中展示时间分片功能的方式。请注意脚本执行时间轴中的小间隙,这些间隙旨在处理用户输入。

能够轻松识别为什么重新渲染组件
工具与开箱即用的性能同等重要。据此,我们可以在Vue 3中看到一个新的生命周期挂钩-renderTriggered。我们可以使用它来跟踪和消除不必要的组件重新渲染,当将其与时间切片结合使用时,这是在运行时性能优化中非常强大的武器。
const Component = {
// other properties
renderTriggered (event) {
console.log(`Re-render of ` + this.$options.name + ` component`, event)
}
}
还有什么
除了上面在Vue 3中看到的内容以外,还有很多内容,但是这些可能是影响最大的更改。大多数未提及的改进将隐藏在Vue编译器生成的代码中,或者与实现细节和算法绑定在一起
但是,有几项改进值得一提:
- 输出代码将更易于针对JavaScript编译器进行优化
- 输出代码通常会更好地进行优化
- 由于改进了补丁算法,将避免不必要的父母/孩子重新渲染
另外,在接下来的几天里,您可以期待Evan You撰写的一篇深入的文章,介绍其专门针对Vue编译器进行的性能优化(发布后,我将使用链接对其进行更新)。
概括
即使Vue已经确立为目前性能最好的框架之一,但我们仍将在第三版中看到重大改进。特别是在捆绑包大小和运行时性能方面。还进行了无数的微优化。我认为Vue 3非常适合现代移动优先和性能导向的网络。
网友评论