当前位置: 首页 > Web前端 > vue.js

你玉玺Vue2设计过程Vue3蜕变?

时间:2023-03-31 23:18:05 vue.js

重写Vue.js下一个主要版本的经验教训在过去的一年里,Vue团队一直在致力于Vue.js的下一个主要版本,我们希望在2020年上半年发布。(在撰写此作品时仍在进行中)。Vue的主要版本于2018年底初具规模,当时Vue2代码库已有两年半的历史。在一般软件的生命周期中听起来可能并不长,但那段时间前端环境已经发生了翻天覆地的变化。两个主要的考虑促使我们开发一个新的主要版本的Vue(并重写它):首先,新的JavaScript语言特性通常在主要浏览器中可用。其次,随着时间的推移,当前代码库中的设计和架构问题已经暴露出来。为什么要重写以利用新的语言特性随着ES2015的标准化,JavaScript(正式名称为ECMAScript,缩写为ES)得到了重大改进,主流浏览器终于??开始对这些新特性提供体面的支持。其中一些特别为我们提供了极大改进Vue功能的机会。其中最值得注意的是Proxy,它允许框架拦截对对象的操作。Vue的一个核心特性是能够监听对用户定义状态所做的更改并响应地更新DOM。Vue2通过用getter和setter替换状态对象的属性来实现这种反应性。切换到Proxy将使我们能够消除Vue的现有限制,例如无法检测新添加的属性并提供更好的性能。但是,Proxy在IE浏览器或旧版本浏览器中存在兼容性问题。为了利用它,我们不得不调整框架的浏览器支持范围,这是一个重大突破,只能在新的大版本中发布。解决架构问题在维护Vue2的过程中,由于现有架构的限制,我们积累了很多难以解决的问题。例如,模板编译器的编写方式使得正确的源映射支持非常具有挑战性。此外,虽然Vue2在技术上允许构建针对非DOM平台的更高级别的渲染器,但我们必须分叉代码库并复制大量代码才能做到这一点。在当前代码库中修复这些问题需要进行大量冒险的重构,这几乎等同于重写。同时,我们以各种模块内部和似乎不属于任何地方的浮动代码之间的隐式耦合形式积累了技术债务。这使得孤立地理解部分代码库变得更加困难,而且我们注意到贡献者很少有信心进行重大更改。重写将使我们有机会重新考虑代码组织,牢记这些注意事项。在当前代码库中修复这些问题需要进行大量冒险的重构,这几乎等同于重写。初始原型制作阶段我们于2018年底开始制作Vue3原型,最初的目标是验证这些问题的解决方案。在这个阶段,我们主要着眼于为进一步发展打下坚实的基础。切换到TypescriptVue2最初是用纯ES编写的。在原型设计阶段之后不久,我们意识到类型系统对于这种规模的项目非常有帮助。类型检查大大降低了在重构过程中引入意外错误的机会,并帮助贡献者更有信心地进行重要更改。我们通过了Facebook的流量类型检查,因为它可以增量添加到现有的ES项目中。交通在一定程度上有所帮助,但我们并没有从我们的希望中得到太多。尤其是不断的变化,让升级变得很痛苦。与TypeScript与VisualStudioCode的深度集成相比,对集成开发环境的支持也不够理想。我们还注意到,用户越来越多地同时使用Vue和TypeScript。为了支持它们的用例,我们必须将TypeScript声明与使用不同类型系统的源代码分开编写和维护。切换到TypeScript将使我们能够自动生成声明文件,从而减少维护负担。解耦内部包我们还采用了monorepo设置,其中框架由内部包组成,每个包都有自己独立的API、类型定义和测试。我们想让这些模块之间的依赖关系更加明确,让开发人员更容易阅读、理解和进行任何更改。这是我们努力降低为项目做出贡献的障碍并提高其长期可维护性的关键。设置RFC流程到2018年底,我们有了一个使用新反应系统和虚拟DOM渲染器的工作原型。我们已经验证了我们想要进行的内部架构改进,但只包含了面向公众的API更改草案。现在是将它们变成具体设计的时候了。我们知道我们必须及早谨慎地做这件事。Vue的广泛使用意味着重大更改可能会导致用户的大量迁移成本和潜在的生态系统碎片化。为确保用户能够就重大更改提供反馈,我们在2019年初采用了RFC(征求意见)流程。每个RFC都遵循一个模板,该模板侧重于动机、设计细节、权衡和采用策略。由于此过程发生在GitHub存储库中,提案作为拉取请求提交,讨论自然会在评论中展开。RFC过程已被证明非常有用,作为一种思想框架,它迫使我们考虑潜在变化的所有方面,让我们的社区参与设计过程,并提交经过深思熟虑的功能请求。更快和更小的性能对于前端框架至关重要。虽然Vue2具有出色的性能,但重写提供了通过尝试新的渲染策略更进一步的机会。克服虚拟DOM瓶颈Vue有一个相当独特的渲染策略:它提供类似HTML的模板语法,但将模板编译成返回虚拟DOM树的渲染函数。该框架通过递归遍历两个虚拟DOM树并比较每个节点上的每个属性来确定实际DOM的哪些部分需要更新。由于现代JavaScript引擎执行的高级优化,这种有点蛮力的算法通常很快,但更新仍然涉及大量不必要的CPU工作。当您查看具有大量静态内容和只有少数动态绑定(整个虚拟DOM)并且仍然需要递归地向上遍历树以查看更改内容的模板时,效率低下尤为明显。幸运的是,模板编译步骤让我们有机会静态分析模板并提取有关动态部分的信息。Vue2通过跳过静态子树在某种程度上做到了这一点,但由于编译器架构过于简单,更高级的优化很难实现。在Vue3中,我们用适当的AST转换管道重写了编译器,这允许我们将编译时优化编写为转换插件。有了新的架构,我们希望找到一种渲染策略,尽可能减少开销。一种选择是放弃虚拟DOM并直接生成命令式DOM操作,但这将消除直接编写虚拟DOM渲染函数的能力,我们发现这对高级用户和库作者非常有价值。另外,这将是一个巨大的突破性变化。其次,最好的方法是消除不必要的虚拟DOM树遍历和属性比较,这往往会在更新期间产生最大的性能开销。为此,编译器和运行时需要协同工作:编译器分析模板并生成带有优化提示的代码,而运行时将获取提示并尽可能采用快速路径。这里有三个主要的优化工作:首先,在树级别,我们注意到节点结构完全静态,没有动态更改节点结构的模板指令(例如v-if和v-for)。如果我们将模板划分为由这些结构指令分隔的嵌套“块树”,则每个块内的节点结构再次变得完全静态。当我们更新块内的节点时,我们不再需要递归遍历树,并且可以在平面数组中跟踪该块内的动态绑定。通过将我们需要执行的树遍历量减少一个数量级,这种优化避免了虚拟DOM的大部分开销。其次,编译器主动检测模板中的静态节点、子树甚至数据对象,并将它们提升到生成代码中的渲染函数之外。这避免了在每次渲染时重新创建这些对象,从而大大提高了内存使用率并降低了垃圾收集的频率。第三,在元素级别,编译器还根据需要执行的更新类型,为每个具有动态绑定的元素生成一个优化标志。例如,具有动态类绑定和许多静态属性的元素将收到一个标志,指示只需要进行类检查。运行时将获取这些提示并采用专用的快速路径。最小化包大小框架的大小也会影响它的性能。这是Web应用程序唯一关心的问题,因为资产需要动态下载,并且应用程序将是交互式的,直到浏览器解析必要的JavaScript。对于单页应用程序尤其如此。尽管Vue一直比较轻量级(Vue2的压缩运行时大小为23KB),但我们注意到两个问题:首先,并不是每个人都使用框架的所有功能。例如,从不使用过渡的应用程序仍将因下载和解析与过渡相关的代码而收费。其次,随着我们添加新功能,框架会无限增长。当我们考虑新功能增加的权衡时,这使得捆绑包的大小不成比例。因此,我们倾向于只包含大多数用户会使用的功能。理想情况下,用户应该能够在构建时删除未使用的框架功能,也称为“tree-shaking”,这样性能损失就会更有弹性,使用的方法越少,性能越好。这也将使我们能够发布一部分用户会觉得有用的功能,而不会增加其余用户的有效负载成本。在Vue3中,我们通过将大部分全局API和内部帮助器移动到ES模块导出来实现这一点。这允许现代打包器静态分析模块依赖关系并删除与未使用的导出相关的代码。框架的某些核心设计部分不会改变,因为它们对于任何类型的应用程序都是必不可少的。我们将这些基本部分的度量称为基线大小。尽管添加了许多新功能,但Vue3的基线大小压缩后约为10KB,不到Vue2的一半。满足规模需求我们还想提高Vue处理大型应用程序的能力。我们最初的Vue设计着重于降低进入门槛和缓和的学习曲线。但是随着Vue被更广泛地采用,我们更多地了解了由数百个模块组成并由数十名开发人员长期维护的项目的需求。对于这些类型的项目,像TypeScript这样的类型系统和干净地组织可重用代码的能力是至关重要的,而Vue2在这些领域的支持并不理想。在设计Vue3的早期阶段,我们试图通过提供对使用类编写组件的内置支持来改进TypeScript集成。挑战在于,我们需要使类可用的许多语言特性(例如Class和Decorator)仍然是提案,并且在它们正式成为JavaScript的一部分之前可能会发生变化。所涉及的复杂性和不确定性让我们怀疑添加类API是否真的合理,因为它除了提供更好的TypeScript集成之外没有提供任何其他东西。我们决定研究解决缩放问题的其他方法。受ReactHooks的启发,我们考虑公开一个较低级别的反应性和组件生命周期API,以更自由的方式编写组件逻辑,称为CompositionAPI。CompositionAPI不是通过指定一长串选项来定义组件,而是允许用户像编写函数一样自由地表达、编写和重用有状态的组件逻辑,同时提供出色的TypeScript支持。我们对这个想法感到非常兴奋。尽管CompositionAPI旨在解决特定类别的问题,但从技术上讲,它仅在组合组件时可用。在提案的初稿中,我们提前暗示我们可能会在未来的版本中用CompositionAPI替换现有的OptionsAPI。这导致了社区成员的强烈反对,这为我们提供了宝贵的经验教训,可以清楚地传达长期计划和意图,以及了解用户需求。在听取了我们社区的反馈后,我们对提案进行了彻底的重新设计,明确CompositionAPI将作为Options的补充和补充API。修改后的提案反响更加积极,收到了很多建设性意见。寻找一个平衡点在超过一百万的Vue开发者中,有HTML/CSS基础知识的初学者,有从jQuery迁移过来的前端工程师,有从其他框架转来的开发者,也有正在寻找前端的人。-端解决方案后端工程师以及大规模处理软件的软件架构师。开发人员的多样性对应于用例的多样性:一些开发人员可能希望向遗留应用程序添加交互性,而其他开发人员可能需要快速周转但维护需求有限的一次性项目。工程师可能不得不在项目的整个生命周期中处理大型的、多年的项目和不断变化的开发团队。当我们寻求平衡各种权衡时,Vue的设计不断受到这些需求的影响和启发。Vue的标语“渐进式框架”封装了由此过程产生的分层API设计。初学者可以使用CDN脚本、基于HTML的模板和直观的OptionsAPI轻松学习,而有经验的同志可以使用功能齐全的CLI、渲染函数和CompositionAPI来处理您的问题。要实现我们的愿景还有很多工作要做,最重要的是,更新支持库、文档和工具以确保顺利迁移。在接下来的几个月里,我们将继续努力,我们迫不及待地想看看社区将使用Vue3创建什么。原文地址:`Theprocess:MakingVue3更多关于Vue技术的内部信息