尤雨溪谈Vue的进化历程

我心飞翔 分类:vue

Vue的进化历程

12 月 10 日,第五届 Vue.js 开发者大会(VueConf 2022)由 Vue.js 官方通过在线直播的方式举办。Vue.js 作者尤雨溪发表了题为 《Vue 的进化历程》 的演讲,下面就来看看这场演讲的具体内容吧!

库阶段

2013-2015年,可以看做是 Vue 的库阶段。那库和框架的区别到底是什么?库更多的是嵌入到已有的体系,只是拿开简单使用。而框架会定义更加广泛的一套工程实践,遵循一定的最佳实践,用配套的工具去遵循一套完整的规范。所以当时的 Vue 只是一个库。

库阶段的重要里程碑:

  • 2013.12:发布第一个以“Vue.js”命名的版本(0.6.0),在此之前的版本都叫 Seed;
  • 2014.02:第一次在 HackerNews 上公开发,公开后的第一周获得了 400+ Github Star;
  • 2014.10:第一次实现 Vue SFC 单文件组件(vueify),使用 Browserify 打包;
  • 2014.11:第一次完全重写(0.11),考虑如何让它更适合用在生产环境中。

库阶段的设计重点:

  • 基于 ES5 的 getter/setters 和原生 JavaScript 对象实现响应式系统,当时的设计重点就是满足个人设计和实现上的想法和兴趣;
  • 基于响应式系统实现模版数据绑定(MVVM);
  • 设计重点就是能像 JQuery 一样可以直接通过

库阶段的特征:

  • Vue 还不算一个框架;
  • 当时的 API 受到了 Backbone/Ractive 的影响:
    • 响应式系统和组件实例有很强的耦合,所有响应式的内容都需要通过在this上做操作来实现,这样的实现比较直观,容易理解,符合基于class思考的思维模式,但是会影响逻辑复用;
    • 直到 0.11 版本才引入 Mixins(混入);
  • 该阶段还在摸索完善模板语法和作用域规则,每个版本的模板语法都会有比较重大的变动,并且作用域规则不是很明确;
  • 基于 DOM 的渲染机制:
    • 模板和编译后的 JavaScript 之间没有对应性,当时的 Vue 并没有“编译”过程;
    • 当时的 Vue 的实现通过把模板直接实例化为 DOM 树;
    • 遍历实例化之后的 DOM 树,在遍历过程中实现数据绑定;
    • 类似于现在 petite-vue 的实现,它是在 Vue 3 之后,重新将 Vue 1 的实现构成一个更轻量的实现,可以将 petite-vue 认为是 Vue 1的一个新的展现, 把 Vue 1 的实现以更现代的方式去提供出来,其更适用于更轻量化的、不需要很多工程化介入的场景。

框架阶段

2015-2016 年,Vue 就进入了框架阶段,以 1.X 版本为目标。

框架阶段的重要里程碑:

  • 2015.08:发布第一版 Vue Router;
  • 2015.09:基于0.11、0.12版本开始开发 Vue 1.0,主要是完善模板语法;
  • 2015.10.26:发布 Vue 1.0,代号为 Evangelion;
  • 2015.12:发布第一版 vue-cli,它更像是一个拉模板的工具,将配置好的模板拉到本地;
  • 2016.03:发布第一版 Vuex。

框架阶段的设计重点:

  • 稳定模板语法和作用域的设计:
    • 确定了 v-bind、v-on 和对应简写的语法;
    • 第一次引入了 v-for(取代了 v-repeat);
  • 将 Vue 项目的涵盖范畴扩大到了单页面应用(SPA)框架
    • SPA 路由;
    • 状态管理;
    • 工具链:实现了单文件组件的热更新支持和Scoped CSS。

通用框架阶段

2016-2019年,Vue 进入了通用框架阶段。

通用框架阶段的重要里程碑:

  • 2016.03:第一次明确提出“渐进式框架”的概念;
  • 2016.04:开始开发 Vue 2.0,尤雨溪正式离职开始全职开发 Vue;
  • 2016.10.01:发布 Vue 2.0,代号为 Ghost in the Shell;
  • 2016.11:发布 Vue 2.1,代号为 Hunter X Hunter,引入了作用域插槽;
  • 2017.02:发布 Vue 2.2,代号为 Initial D,SSR 支持基于路由的代码分割,每个路由的代码可以懒加载;
  • 2017.04:发布 Vue 2.3,代号为 JoJo,SSR 支持基于路由的资源预加载;
  • 2017.06:发布 Vue 2.4,代号为 Kill la Kill,SSR 完整异步组件支持,可以在 SSR 应用的任何地方使用异步组件,引入了部分优化的 SSR 编译输出;
  • 2018.01-08:开发 Vue Cli 3.0,进一步扩展框架的边界,将工具链视为框架的一部分;实现针对 SPA 的高度集成的工具链,有插件机制,开箱即用,集成 TypeScript 、单元测试、ESLint 等;

Vue 2.0 阶段的设计重点:

  • Vue 的第二次彻底重写,目标是改进代码的架构,提高其长期的可维护性,目前来看 2.0 版本的可维护性依然是相当可以的;
  • 引入了将模板编译为 Virtual DOM 渲染函数的编译流程,也就是在 2.0 才引入了“模板编译”的概念;
  • 基于 Virtual DOM 的服务端渲染(SSR),先编译为 Virtual DOM 的渲染函数,生成 Virtual DOM,再将 Virtual DOM 字符串化,类似于 React 的服务端渲染;
  • 基于 Virtual DOM 的 跨端渲染(整合 Weex,NativeScript);
  • 结合类型系统:
    • 在源码中使用 Flow 定义类型;
    • 直到现在,2.x 版本的 TypeScript 类型定义都需要手动维护,而不是从源代码中生成的,这也是在 Vue 3 中使用 TypeScript 进行重写的原因之一。

这个阶段的一个重要 demo 就是:vue-hackernews-2.0,在当时这个 demo 有重要的意义:

  • 使用 Webpack + SFC + Vue Router + Vuex + SSR 实现;
  • 第一个完整展示 Vue 2 SSR 架构的 demo,包含了相关的 Webpack 配置,单文件组件如何针对客户端和服务端进行不同的编译配置,如何在重构的架构中使用路由、状态管理等;
  • 利用这个 demo 做了很多 Vue 2 SSR 功能的开发,通过这个 demo 来测 Vue 2 SSR 在实际开发中是否易用;
  • 这个 demo 更重要的意义是启发了上层的 SSR 框架,比如 Nuxt.js,Nuxt 最初就参照这个 demo 实现,并吸取了 Next.js 的经验。

编译/运行时混合阶段

2019年至今,Vue 进入了编译/运行时混合阶段。虽然 2.0 阶段引入了编译,但是 2.0 的编译和运行时的结合是非常浅的结合,编译器编译出 Virtual DOM 渲染函数就到此为止了,编译器对运行时是怎么样的并没有太多概念,而运行时对于编译器也是没有概念的,这样很多优化空间就被浪费了。所以 3.0 阶段的主要目标就是让编译器和运行时都属于框架的一部分,它们本身就是耦合的。 在耦合的前提下,让编译器为运行时提供更多的信息,让运行时知道编译器提供的信息。

编译/运行时混合阶段的重要里程碑:

  • 2018.09:在 Vue.js London 宣布 Vue 3 的开发计划;
  • 2018.09 - 2019.05:调研阶段;
  • 2019.05:实现基于编译优化 Virtual DOM 性能的新策略;
  • 2019.08:提出 Composition API RFC;
  • 2020.01:发布 Vue 3.0 alpha 版本;
  • 2020.04:发布 Vue 3.0 beta 版本,引入了完全优化的 SSR 编译输出,如果组件是用模板写的,那它的 SSR 编译输出不存在任何 Virtual DOM 的开销,所有能做成字符串拼接的地方都做成了字符串拼接;
  • 2020.04 - 2021.02:绕道开发了 Vite。
  • 2020.09:Vue 3.0 稳定版正式发布;
  • 2021.06:发布 Vue 3.1 版本,提供 Migration Build,使用可以兼容 Vue 2 的用法让用户更方便的升级;
  • 2021.08:发布 Vue 3.2 版本,引入了

Vue 3.0 重构初期的重心如下:

  • 提高浏览器的最低支持要求,使用现代 ES 语法和功能;
  • 全面提升系统;
  • 改善类型系统的整合;
  • 改善在大型应用中的可扩展性。2018年慢慢开始有有较大型企业、项目开始使用Vue,让 Vue 遇到了新的挑战,在实际的场景中,之前的 Vue 设计在比较大的团队协作的场景中存在可维护性上的问题,希望在 Vue 3 中找到这些问题的解决方案。

Composition API 的意义:

  • Vue 的用例越来越多地进入企业、大型项目领域;
  • Options API 在可扩展性方面有明显的上限,对于重构庞大、臃肿的组件有很大的难度,不能轻松的进行逻辑的重新组织。而 Composition API 对逻辑的可维护、组合、复用提供了很好的解决方案;
  • 因为 Composition API 更多的依赖函数调用,所以对类型系统更友好;
  • 提供灵活且可维护的逻辑组合/复用。

Vite 的意义:

  • Vite 大幅优化了开发体验;
  • 将和框架没有耦合的工具链职责剥离,交给一个更大的社区去维护,这样也会样 Vue 的体验变得更好;
  • 减少 Vue 本身的框架范畴和维护负担:Vue CLI -> create-vue

Vue 3 目前定义的框架范畴:

  • 核心(编译器 + 运行时)
  • 文档
  • 工具链(create-vue)
  • SPA 路由(React Router)
  • 状态管理(Pinia)
  • 浏览器开发工具(vue-devtools)
  • IDE 支持(Volar)
  • TypeScript 支持(vue-tsc)
  • 静态分析(eslint-plugin-vue)
  • 单元测试(@vue/test-utils)
    整体趋势就是向编译/运行时混合模式进化:
  • 同一份模板,不有得编译输出:
    • 在浏览器中:输出高度优化的 Virtual DOM 渲染函数;
    • 在 SSR 中:输出 buffer + 字符串拼接;
    • 将来:Vapar mode(不依赖 Virtual DOM 的渲染代码,获得更好的性能)
  • 在单文件组件中引入更多的语法糖:
    • <script setup>;
    • v-bind():实现动态 CSS 的绑定;
    • Reactivity Transform;

现状

  • 社区现在仍然处于 2 -> 3 的过渡阶段;
  • 2022年6月发布了 Vue 2.7,进一步弥补了 2 和 3 之间的断层,提供了一个 2->3 更缓和的升级流程。不过,如果现在的 Vue 2 项目很稳定,没必要为了升级而升级;
  • 基于目前的 npm 数据:超过 30% 的项目在使用 Vue 3,大概 25% 的项目在使用 Vue 2.7,所以有超过一半的项目已经可以使用 Composition API 和 <script setup>,整体的过渡情况比较乐观。

展望

Vue 团队接下来的工作会以 API 的稳定性为优先,重点会放在不影响使用方式的改进上。不计划引入像 React Server Components 这样需要和服务器强绑定的特性。

  • 短期:
    • 稳定 Reactivity Transform / Suspense,从实验特性变为稳定特性;
    • Vue 3.3 的重点是 SSR 的水合性能改进,提供以异步组件为边界的懒水合和按需水合。
  • 中到长期:
    • Vapor mode(受 Solid 启发的模板编译策略),明年 Vue 团队会更新更多相关信息。

关于 Vapor mode:
完全一样的模板/组件语法可以编译成完全不一样的输出,这个输出不再依赖 Virtual DOM 运行时,而是针对 Web 性能进行特化,可以提供极致的性能和内存占用,还可以在一些情况下做零成本组件抽象,即当组件只使用了基本的 API 时,将它编译成一个不需要组件实例的状态,这样就可以节省一定的组件实例开销。

Vapor mode的使用方式上,可以将它无缝嵌入到现有的应用中,可以兼容基于 Virtual DOM 的第三方库。如果是全新的项目,可以启用 Vapor-only,这样就再兼容 Virtual DOM,丢掉了相关的运行时,适合对性能有极致要求的场景。

回复

我来回复
  • 暂无回复内容