专栏首页前端自习课【Vuejs】397- Vue 3最值得期待的五项重大更新

【Vuejs】397- Vue 3最值得期待的五项重大更新

性能优化

我非常重视性能,所以在探索具体的 API 之前我想谈一谈 Vue 3 的性能。可讲的东西是很多的!几乎每个角落都能找到明显的改进!

首先来看 Vue 3 的包大小。

目前,最小化和压缩过的 Vue 运行时大小约为 20kB(当前的 2.6.10 版本为 22.8kB)。Vue 3 的包估计只需一半的体积,因此只有〜10kB!

全局 API tree-shaking

Vue 3 带来了许多诸如更好的模块化之类的优化,而最值得一提的是 Vue 3 源代码将支持 tree-shaking。这意味着如果你不使用它的某些功能(例如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 支持 tree-shaking,Vue 团队决定通过命名导出导入其中的大多数 API,以便打包器可以检测出未使用的代码并删除它们:

 // 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 的插件,代价就是影响性能。

支持 tree-shaking 的 JavaScript API 不止一个。在后台,Vue 编译器(将 Vue 模板转换为渲染函数的工具)将检测模板中使用的指令,并对其进行 tree-shaking。以下面的模板为例:

<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])
  ])
}

所有人都会从全局 API tree-shaking 中受益(尤其是我们的用户),但我认为最看重这一功能的是那些制作小型,轻量级网站并只使用 Vue 的一部分功能来开发交互的开发者,他们主要用 Vue 来替代 jQuery 之类的库。

基于代理的响应性

包的大小可能会严重影响你的应用加载时间,但是包被完整下载后,它也应该快速渲染并流畅运行。

Vue 核心团队非常了解这一点,因此我们在运行时性能上也有很大的改进。

首先来看影响最大的部分——一种基于 JavaScript 代理的新的响应系统。当前版本的 Vue 响应系统是基于 Object.defineProperty 的,其存在一些局限。最常见且令人沮丧的一个限制是 Vue 无法跟踪响应对象的属性添加 / 删除。为此我们需要使用 Vue.set 和 Vue.delete 来保证响应系统的运行符合预期。有了 JS 代理后,我们终于可以摆脱这种丑陋的解决方案了。

// 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 必须使用 getters/setters 来递归地遍历所有对象及其属性,并转换它们。使用代理后,这一过程就变得容易很多。

值得一提的是,使用 JS 代理后,Vue 3 会放弃对 Internet Explorer 的支持(不包括 Edge),但请放心,对于希望支持 IE 的用户来说会有一个兼容版本可用。

时间分片

根据 Evan You 的推文,此功能不会包含在 Vue 3 中。

Vue 3 之后的版本还会带来另一个非常激动人心,但很少被提到的功能,那就是对时间分片的试验性支持。

打个比方来解释什么是时间分片。想象一家甜品店前排了长长的队伍,因为店里在卖镇上最好的冰淇淋。一个人买到冰淇淋后就轮到下一个,以此类推。由于某种原因,大家不知道有哪些口味可供选择。要获取这一信息,你需要直接询问出售冰淇淋的柜台售货员。

在这种情况下,我们最后可能会看到两条队伍——其中一条是想要买冰淇淋的顾客(耐心等待),另一条则是那些希望在决定是否购买冰淇淋之前了解更多口味信息的顾客。后者希望尽快获得这一信息。不幸的是,只有一位女士在卖冰淇淋,她在为“主”队伍中的所有顾客提供完服务之前不会回答任何问题。

对于还没下决定的顾客来说,这并不是最好的体验,他们中的大多数人可能会觉得等那么久并不值当。为了解决这个问题,卖冰淇淋的女士可以在每服务 2 至 3 位顾客后回答一个关于口味的问题。这样一来两条队伍中的顾客都应该会满意这个解决方案。

这正是 CPU 运行 Web 应用程序的工作机制。我们有一条“主”队列(称为“主线程”),需要完成应用的所有主要任务(脚本、渲染等),然后才能响应用户交互。对于某些页面来说,这可能会导致非常糟糕的用户体验,具体取决于 Vue 组件加载或重新渲染所需的时间。

为了让它更加可靠,最好将这一脚本运算过程“切成”小段,并在每小段执行后查看是否有用户输入要处理。这样,无论需要多少次渲染或重新渲染,应用程序都将保持响应状态。这就是在 Vue 3 未来版本中的工作机制。

Evan 用下面的图片展示了 Vue 3 中时间分片功能的例子。请注意脚本执行时间轴中的小间隙,这些间隙是用来处理用户输入的。

轻松识别为什么组件会重新渲染

工具与开箱即用的性能同等重要。据此,我们会在 Vue 3 中看到一个新的生命周期 hook——renderTriggered。我们可以使用它来跟踪和消除不必要的组件重新渲染,将其与时间分片配合使用,就成为了优化运行时性能的非常强大的武器。

const Component = {
  // other properties
  renderTriggered (event) {
     console.log(`Re-render of ` + this.$options.name + ` component`, event)
  }
}

还有什么

除了上面提到的这些内容,Vue 3 加入的改进还有很多很多,但本文提到的这些更改可能是影响最大的。大多数未提及的改进将隐藏在 Vue 编译器生成的代码中,或者融入实现细节和算法中。

还有几项改进值得一提:

  • 输出代码将更容易针对 JavaScript 编译器优化。
  • 输出代码通常会更好地优化。
  • 由于改进了补丁算法,将避免不必要的父级 / 子级重新渲染。

总 结

尽管 Vue 已经称得上是目前性能最好的框架之一,但我们还是会在第三版中看到许多重大改进,特别是在包大小和运行时性能等方面。此外 Vue 3 还带来了无数细小的优化。我认为 Vue 3 非常适合现代移动优先和性能导向的 Web 开发工作。

别忘了 Vue 是唯一由社区完全驱动的主流框架。本文列出的所有更改(和其他更多更改)都以 RFC 的形式与社区一起讨论过了。你可以帮助核心团队,表达你对活跃 RFC 的意见,甚至可以提出自己的改进建议。

让我们一起使 Vue 变得更好?

下一步计划

在下一篇文章中,我们将探讨新的 Vue 3 API 将如何影响我们编写 Web 应用程序的方式。我们将研究各种 API,包括最近流行的 Composition API,并了解如何使用它来编写更好和更易维护的代码。

本文分享自微信公众号 - 前端自习课(FE-study)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 别在不知道临时死区的情况下使用 JavaScript 变量[每日前端夜话0xD2]

    正确答案:第一个代码段(带有类)将生成 ReferenceError。第二个工作正常。

    疯狂的技术宅
  • 8种主流NoSQL数据库对比

    摘要:虽然SQL数据库是非常有用的工具,但经历了15年的一支独秀之后垄断即将被打破。这只是时间问题:被迫使用关系数据库,但最终发现不能适应需求的情况不胜枚举。

    小小科
  • 在 JavaScript 中轻松处理 this [每日前端夜话0xD1]

    我喜欢 JavaScript 中能够更改函数执行上下文(也称为 this)的特性。

    疯狂的技术宅
  • [ASP.NET Core 3框架揭秘] 依赖注入:IoC模式

    正如我们在《依赖注入:控制反转》提到过的,很多人将IoC理解为一种“面向对象的设计模式”,实际上IoC不仅与面向对象没有必然的联系,它自身甚至算不上是一种设计模...

    蒋金楠
  • 什么是响应式流?

    本文来源:https://blog.csdn.net/get_set/article/details/79466402

    Java3y
  • Java并发编程75道面试题及答案——稳了

    任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bool on);true则把该线程设置为守护线程,反之则为用户线程。Thre...

    搜云库技术团队
  • javascript当中表单提交(空格提交的问题)

    4.表单提交(空格提交的问题) 例 4.1(form.submitIEFF.html) <head> <meta http-equiv="conten...

    马克java社区
  • webpack的运行机制详解

    webpack是现代前端开发中最火的模块打包工具,只需要通过简单的配置,便可以完成模块的加载和打包。那它是怎么做到通过对一些插件的配置,便可以轻松实现对代码的构...

    前端迷
  • 测试开发进阶(二十六)

    如果在创建序列化器对象时候,只给data传参,那么调用save()方法实际调用的就是序列化器对象的 create()方法 在创建序列化器对象时,同时给ins...

    zx钟
  • [VSCode插件推荐] Code Runner: 代码一键运行,支持超过40种语言

    安装好Code Runner之后,打开你所要运行的文件,有多种方式来快捷地运行你的代码:

    心莱科技雪雁

扫码关注云+社区

领取腾讯云代金券