2014 年 2 月 3 日,Vue 在 Hacker News 上首次亮相。十年后的今天,Vue 已经成为使用最广泛的前端框架之一,拥有了一个非常丰富的生态系统。本文来梳理一下 Vue.js 十年以来的重要里程碑!
图片
尤雨溪,无疑是 Vue.js 背后的灵魂人物。早在 2013 年,他还在 Google 工作,便接触到了 Google 团队开发的强大前端框架 Angular。他对 Angular 的产生了兴趣,但觉得它并不完美。因此,决定打造一款更为轻量且用户友好的前端框架,这就是我们今天所熟知的 Vue.js。自此,Vue 的故事就开始了...
图片
库阶段(2013-2015)
在 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 一样可以直接通过<script>标签直接引用的简单库,这种方式不会对其他方面产生意见和限制。
库阶段的特征:
- 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)
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)
2016-2019 年,Vue 进入了通用框架阶段,以 2.X 版本为目标。
图片
通用框架阶段的重要里程碑:
- 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.07:发布 Vue 2.4,代号为 Kill la Kill,SSR 完整异步组件支持,可以在 SSR 应用的任何地方使用异步组件,引入了部分优化的 SSR 编译输出;
- **2017.10:发布 Vue 2.5,代号为 Level E,**该版本引入了新的错误处理钩子函数、改进了模板表达式错误消息和选项类型检查、提供更好的TypeScript类型声明支持。
- **2019.2:**发布 Vue 2.6,代号为 Macross,该版本实现了新的v-slot语法、在函数式组件中添加了scopedSlots、为生命周期钩子和v-on处理程序提供了同步和异步错误处理、支持动态指令参数、添加了Vue.observable()方法用于创建可观察对象、在$scopedSlots上暴露了所有普通插槽等。
- 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:
- 使用 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-至今)
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 版本,引入了 <script setup>。
- 2022.01:Vue 3 正式切换为默认版本,此时 Vue 3 框架范畴内的工具都准备完毕;
- 2022.02:发布全新的 Vue 3 文档;
- 2022.06:发布 Vue 2.7,进一步弥补了 2 和 3 之间的断层,提供了一个 2->3 更缓和的升级流程。不过,如果现在的 Vue 2 项目很稳定,没必要为了升级而升级;
- 2023.05:发布 Vue 3.3,主要针对开发者体验进行了改进,特别是在使用 TypeScript 时的 SFC <script setup>,解决了在使用 TypeScript 时存在的许多长期困扰问题。
- 2023.12:发布 Vue 2.7.16,版本号为 Swan Song,意为绝唱。这是 Vue 2 的最后一个版本。
- 2023.12:发布 Vue 3.4,该版本重写了模板解析器。新的解析器将速度提高了 2 倍,显著提升了整体性能。此外,响应性系统也经过了重构,使得 effect 触发更为精确和高效。
- 2023.12.31:Vue 2 正式停止维护,团队将把精力全部放在维护 Vue 3 上。
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
整体趋势就是向编译/运行时混合模式进化:
- 同一份模板,不同的编译输出:
在浏览器中:输出高度优化的 Virtual DOM 渲染函数;
在 SSR 中:输出 buffer + 字符串拼接;
将来:Vapar mode(不依赖 Virtual DOM 的渲染代码,获得更好的性能)
- 在单文件组件中引入更多的语法糖:
- <script setup>;
- v-bind():实现动态 CSS 的绑定;
- Reactivity Transform
面向未来
Vue 团队目前在重点开发 Vapor mode。这是一种正在试验中的编译策略,其灵感来源于 Solid。对于相同的 Vue SFC,与当前基于虚拟 DOM 的编译结果相比,Vapor Mode 能够生成性能更高、内存使用更少、运行时支持代码更少的 JavaScript 输出。它的目标是通过编译为更高效的 JavaScript 来提升应用的性能。当在应用级别使用时,Vapor Mode 可以完全去除虚拟 DOM,从而减小应用的包大小,进一步优化应用的性能。
Vue 2 已经停止维护,这是一个时代的结束,也是一个新时代的开始,2024 年对 Vue 来说将是激动人心的一年!