主机参考:VPS测评参考推荐/专注分享VPS服务器优惠信息!若您是商家可以在本站进行投稿,查看详情!此外我们还提供软文收录、PayPal代付、广告赞助等服务,查看详情! |
我们发布的部分优惠活动文章可能存在时效性,购买时建议在本站搜索商家名称可查看相关文章充分了解该商家!若非中文页面可使用Edge浏览器同步翻译!PayPal代付/收录合作 |
微信小程序开发教程专栏介绍了Rax小程序运行时的方案。2020年3月,在支持编译时方案后,Rax小程序发布了支持运行时方案的版本。到目前为止,Rax仍然是业界唯一同时支持编译时和运行时方案的小程序开发框架。本文将介绍Rax applet运行时方案的原理和我们的思考。
回顾编译时方案在介绍运行时方案之前,我们先回顾一下什么是编译时方案。顾名思义,编译时方案侧重于编译,代表框架是tarov2.x,通过静态编译的方式,将JSX转换成小程序的模板语言(即WXML/AXML等。),辅以轻量级运行时JS代码,抹平了小程序生命周期与React生命周期的差异,让用户可以用熟悉的React DSL开发小程序。Rax的编译时方案原理和Taro v2.x类似,实现细节请参考之前的文章《Rax到Applet的链接原理分析(一)》和《Rax Applet的编译时方案原理分析》。与编译时方案不同,运行时方案侧重于运行时的渲染能力,不依赖静态编译,因此几乎没有语法限制,这也是其最大的特点。让我们来看看运行时方案的实现原理。
基础小程序的底层实现其实是基于Web技术的,但是反映到开发者层面就和Web大不相同了。在applet中,逻辑层与视图层是隔离的。逻辑层通过特有的setData方法向视图层传输数据触发渲染,视图层通过事件触发逻辑层代码。其架构如下图所示。相比Web开发,开发者可以使用JS调用浏览器提供的DOM/BOM API随心所欲地操作和渲染内容。applet的架构更封闭,更安全,但也意味着Web代码不能直接在applet上运行。
对于现代前端框架(React/Vue),底层基本上是通过调用DOM API来创建视图。但是小程序的视图层模板需要开发者提前编写,也就是说小程序中不允许动态创建DOM的方式。然而,applet自定义组件的“自引用”特性为动态创建DOM打开了一个突破口。自引用是指自定义组件支持使用自身作为子节点,这意味着我们可以通过递归引用来构造任意级别和任意数量的DOM树。
例如,假设一个小程序自定义组件元素的WXML模板如下:
ltview wx:if = ;{ { r.tagName = = = # 39查看 # 39;} } id = { { r.nodeId } } gt ltblock wx:for = " { { r . children } } " wx:key = ;节点 gt lt元素数据= { { r:item } } ;/ gt; lt/block gt; lt/view gt; lttext wx:elif = ;{ { r.tagName = = = # 39正文 # 39;} } gt{ { r.content } } lt/text gt;复制代码注意到元素在模板中递归引用了自己,并通过条件判断终止了递归。然后,当逻辑层通过setData传递以下数据时:
{ 节点 : 1 , 标记名: 查看 , 儿童 :
event Rax小程序运行时,模拟DOM/BOM API的库是miniapp-render,支持的API如下:
除了处理渲染数据,另一个重要的是事件系统。它通过EventTarget基类实现了完整的事件调度机制。逻辑层DOM节点都继承自EventTarget,通过唯一的nodeId收集自己的绑定事件。图层模板上的每个内置组件都将绑定nodeId,并侦听所有可触发的事件,例如一个简单的视图标记,它将绑定bind tap/bindtuchstart/bindtuchend和其他事件。事件触发时,通过event . current target . dataset . nodeid获取目标节点的id,然后触发用户在该节点上绑定的相应函数。
设计Rax applet运行时的主要工程流程遵循Rax Web的设计,Web端Webpack封装的JS Bundle可以在applet运行时重用。我们通过插件将miniapp-render模拟的窗口和文档变量注入到这个bundle中,然后生成一个固定的小程序项目骨架,然后在app.js中加载JS Bundle其整体工程结构如下图所示:
MPA还是SPA?以上架构是逐渐演变的结果。起初,我们使用webpack的多入口模式来封装运行时小程序代码,即每个页面都会作为一个入口独立封装。这使得applet的行为更像一个MPA。这就带来了页面之间的共同依赖代码不在同一个内存中执行的问题,与原生小程序的性能不一致。这种差异导致我们最终决定改变工程包装模式。目前版本的Rax运行时小程序更符合SPA,所有业务代码打包成一个JS文件。
我们在小程序的运行时上修改了Rax项目入口Rax-app包的链接,它会在初始化时按照路线返回各个页面的渲染函数。render函数创建根节点(document.createElement)以在其上安装相应的RAX组件,并将根节点附加到正文节点(document.body.appendChild)上。小程序的每一页都会创建一个独立的文档并在onLoad生命周期内将其设置为全局变量,然后调用其对应的render函数独立渲染每一页。
性能调优从上述小程序的运行时原理来看,其性能与原生相比有一定差距,主要由以下几个方面造成:一是Rax+,完全运行在逻辑层,通过模拟DOM/BOM API处理VDOM并生成setData数据,需要更多的计算时间;其次,与原生小程序相比,需要传输更多的setData数据,如果容器层数据序列化能力较弱,会大大增加数据传输时间;第三,视图层通过自定义组件动态递归生成视图,我们知道递归动作本身就是一个性能损失点。另外,由于无法提前知道用户需要绑定的属性和事件,所有的属性和事件只能在自定义组件模板中提前绑定,导致小程序运行过程中触发了很多无用的事件,进一步增加了负担。根据我们的基准计算,在支付宝小程序平台上,运行时小程序框架(包括Rax/Taro/Remax等)之间有40%左右的性能差距。)和原生小程序。
Rax小程序运行时发布后,经过测试其性能明显不同于其他运行时框架,所以我们开始了专门的性能调优计划。通过以下几个方面的重构,Rax小程序的性能成功提升到业界领先水平,与Taro/Remax基本处于同一水平。
更新数据精度。在旧版本中,setData的数据是完全更新的。虽然有dom子树划分和批量更新的设计,但是数据传输还是有很多冗余。在重构版本中,Rax增加了节点渲染判断,卸载的节点不需要触发更新;所有更新都汇聚到顶层根节点进行统一批处理,通过精确计算数据更新的路径实现局部更新。例如,当更新一个节点的class属性时,setData的数据可能是:
{ root.children.[0].children.[1].class : 活动 }复制代码的内置applet组件不需要维护其属性列表,而是直接根据用户传递的参数赋值。在旧版本中,我们维护所有内置组件的属性,在获取属性值时都需要调用domNode.getAttribute,这有一定的性能开销。重构版Rax直接根据用户传递的参数给属性赋值,将设置默认值的操作移到视图层的WXS/SJS进行处理。
更新miniapp-render中的数据结构。经过梳理,Rax去掉了冗余的树数据,重写了API如getaElementById重构的类,如attribute和classList使用了更符合场景需求的Map/Set等数据结构,提升了整体数据处理性能。
模板优化。支付宝小程序中,Rax使用模板进行递归调用;在微信中,Rax采用模板调用元素再模板的形式,避免了微信递归调用模板的层数限制。在模板中,我们尽量使用模板is语法进行判断,减少a:if/wx:if条件判断,提高模板递归的性能。
混合使用无论是为了旧业务的迁移,还是出于性能的考虑,Rax小程序的运行时都需要混合使用。目前Rax已经可以和小程序的内置组件、自定义组件、页面、插件混合使用。其中,使用小程序定制组件是最复杂的。
混合小程序自定义组件。在Rax中使用applet自定义组件时,其引入路径需要与usingComponents一致(例如,import CustomComp from # 39../components/custom comp/index # 39;)。在编译阶段,Rax项目使用Babel插件进行静态代码分析。当检测到JSX使用的组件是小程序自定义组件(根据其导入路径中是否有同名的axml文件)时,会缓存其使用的属性和事件,然后通过webpack插件动态生成到递归模板中。在运行时的节点创建阶段,通过查询缓存来判断节点是否为自定义组件。如果是自定义组件,缓存中的属性将被插入到其呈现数据中,并且事件将被绑定到自定义组件实例。
与编译时组件混合(双引擎混合)Rax小程序编译时方案产生的组件,从使用形式上可以直接视为小程序自定义组件。Rax项目加强了运行时和编译时之间的联系。在Rax小程序运行时使用编译时组件npm包时,用户不需要引入组件的具体路径,就像使用普通组件一样。Rax项目会根据组件的package.json中是否有miniappConfig字段来自动判断是否是Rax多端组件,然后直接使用其编译后的组件来实现。
优化的未来方向Rax作为业界唯一同时支持编译期和运行期引擎的小程序开发方案,凭借其同时使用两种引擎的能力,可以完美平衡性能和开发效率。未来,Rax将实现更灵活的双引擎混合使用模式,例如在单个项目中指定一个组件由编译时引擎编译,为业务提供更高的灵活性。
以上总结是Rax小程序运行时方案的原理分析。运行时方案解决了编译时方案固有的语法限制,但也有明显的性能约束。可以说,在2020年的当前节点,小程序开发依然没有所谓的银弹,或许Rax小程序的双引擎整合会是一个相对范围内的最优解。一个违背标准的小程序能走多远,没有人能下结论。在未来相当一段时间内,开发商还是要面对各种问题。站在小程序开发框架的角度,只希望所有开发者都能选择最适合自己的框架,快速高效的完成小程序的开发。
那就是解密的细节和思考Rax小程序的运行时方案。请多关注主机参考其他相关文章!
这几篇文章你可能也喜欢:
本文由主机参考刊发,转载请注明:Rax Applet运行时方案的解密与思考 https://zhujicankao.com/81865.html
评论前必须登录!
注册