Maison > Article > Applet WeChat > Décryptage et réflexion sur la solution d'exécution de l'applet Rax
La colonne
En mars 2020, après avoir pris en charge le schéma de compilation, l'applet Rax a publié une version qui prend en charge le schéma d'exécution. Jusqu'à présent, Rax est toujours le seul petit framework de développement de programmes du secteur qui prend en charge à la fois les solutions de compilation et d'exécution. Cet article vous présentera les principes de la solution d'exécution de l'applet Rax et notre réflexion.
Avant de présenter la solution au moment de l'exécution, examinons ce qu'est la solution au moment de la compilation. Comme son nom l'indique, la solution de compilation se concentre sur la compilation et le framework représentatif est Taro v2.x. Il convertit JSX dans le langage de modèle du mini-programme (c'est-à-dire WXML/AXML, etc.) via une compilation statique, puis le complète avec du code JS d'exécution léger pour lisser la différence entre le cycle de vie du mini-programme et le cycle de vie de React. , ce qui permet aux utilisateurs de développer de petits programmes avec le React DSL familier. Le principe du schéma de compilation de Rax est similaire à celui de Taro v2.x Pour les détails d'implémentation, vous pouvez vous référer aux articles précédents Analyse du principe du lien Rax vers Mini Program (1) et Analyse du principe du lien. Schéma de compilation du programme Rax Mini. Différente de la solution au moment de la compilation, la solution au moment de l'exécution se concentre sur l'implémentation des capacités de rendu au moment de l'exécution et ne repose pas sur la compilation statique. Par conséquent, il n'y a presque aucune restriction de syntaxe, ce qui constitue sa principale fonctionnalité. Jetons un coup d'œil aux principes de mise en œuvre des solutions d'exécution.
La mise en œuvre sous-jacente des mini-programmes est en fait basée sur la technologie Web, mais lorsqu'on y réfléchit au niveau du développeur, elle est assez différente du Web. Dans le mini programme, la couche logique et la couche vue sont isolées. La couche logique transmet les données à la couche vue pour déclencher le rendu via la seule méthode setData
, et la couche vue déclenche le code de la couche logique via des événements. illustré dans la figure ci-dessous. Par rapport au développement Web, les développeurs peuvent utiliser JS pour appeler l'API DOM/BOM fournie par le navigateur afin de manipuler et de restituer le contenu à leur guise. L'architecture des mini-programmes est plus fermée et plus sûre, mais cela signifie également que le code Web ne peut pas s'exécuter directement. sur les mini programmes.
Pour les frameworks front-end modernes (React/Vue), la couche inférieure crée essentiellement des vues en appelant l'API DOM. Le modèle de couche de vue du mini-programme doit être écrit par le développeur à l'avance, ce qui signifie que la méthode de création dynamique de DOM n'est pas autorisée dans le mini-programme. Cependant, la fonctionnalité « d'auto-référence » du composant personnalisé du mini-programme ouvre une avancée majeure dans la création dynamique de DOM. Ce qu'on appelle l'auto-référence signifie que le composant personnalisé prend en charge son utilisation comme nœud enfant, ce qui signifie que grâce à la référence récursive, nous pouvons construire n'importe quel niveau et n'importe quel nombre d'arborescences DOM.
Par exemple, supposons que le modèle WXML d'un élément de composant personnalisé d'un petit programme soit le suivant :
<view> <block> <element></element> </block></view><text> {{r.content}}</text>复制代码
Remarquez que l'élément fait référence à lui-même de manière récursive dans le modèle et termine la récursion par jugement conditionnel. Ensuite, lorsque la couche logique transmet les données suivantes à travers setData
:
{ "nodeId": "1", "tagName": "view", "children": [ { "nodeId": "2", "tagName": "text", “content”: “我是?" }, { "nodeId": "3", “tagName": "text", "content": "rax" } ] }复制代码
La vue finale devient :
<view> <text>我是</text> <text>rax</text></view>复制代码
De cette façon, nous réalisons intelligemment Fournit la possibilité de restituer dynamiquement des vues basées sur données setData
entrantes lorsque le modèle WXML est corrigé. Et c’est la base de la naissance des solutions d’exécution.
La solution d'exécution de Rax est dérivée de kbone, une solution isomorphe pour les mini-programmes et la fin du Web officiellement lancée par WeChat. Les principes de conception de kbone peuvent être renvoyés à l'introduction de son site Web officiel. Un résumé simple consiste à simuler l'API DOM/BOM au niveau de la couche logique, à convertir ces méthodes de création de vues en maintenance d'une arborescence VDOM, puis à la convertir en données correspondant à. setData
. Enfin, la vue réelle est rendue récursivement via le modèle prédéfini. Le principe de base du processus depuis l'API DOM jusqu'à la maintenance de l'arborescence VDOM n'est pas compliqué. createElement/appendChild/insertBefore/removeChild et ainsi de suite correspondent aux opérations de base de la structure de données.
Les étudiants qui connaissent Rax doivent savoir que pour prendre en charge plusieurs terminaux, Rax a une conception de pilote. En fait, nous pouvons écrire un autre pilote pour le petit programme et implémenter son API d'interface basée sur les principes ci-dessus. Mais notre choix final a été de compléter l’ensemble du mécanisme de rendu via une API BOM/DOM simulée de niveau inférieur. Les considérations pour cela sont, d'abord, basées sur le développement de kbone, qui est la solution la plus rapide. Le pilote côté applet n'a besoin que de réutiliser le pilote côté Web. Après tout, les document
et les variables sont les deux. Cela a été simulé ; deuxièmement, c'est parce que nous souhaitons offrir aux développeurs une expérience de développement plus proche du web. Cette solution signifie qu'en plus d'utiliser JSX, les développeurs peuvent également utiliser directement l'API BOM/DOM pour créer des vues, qui seront plus flexibles. Nous examinons tous les frameworks d'exécution de mini-programmes sur le marché. Remax s'interface directement avec les mini-programmes de la couche VDOM via React-Reconciler (similaire à la conception du pilote de mini-programme Rax mentionnée ci-dessus), tandis que Kbone et Taro 3.0 choisissent tous deux d'utiliser la simulation. .Environnement Web pour implémenter le rendu. Ceci est également lié à l'intention de conception du développeur du framework, et les opinions varient. Le schéma de base de la solution d'exécution de l'applet Rax est le suivant : window
. Les nœuds DOM de la couche logique héritent tous de EventTarget
et collectent leurs propres événements de liaison via l'unique EventTarget
. Chaque composant intégré sur le modèle de couche de vue sera lié à nodeId
et écoutera tous les événements déclenchables. Par exemple, une simple balise de vue liera bindtap/bindtouchstart/bindtouchend et d'autres événements. Lorsque l'événement est déclenché, l'identifiant du nœud cible est obtenu via nodeId
, puis la fonction correspondante liée par l'utilisateur sur le nœud est déclenchée. event.currentTarget.dataset.nodeId
de chaque page en fonction du parcours. La render
La fonction crée un nœud racine (render
), y monte le composant Rax correspondant et ajoute le nœud racine au nœud corps (document.createElement
). Pendant le cycle de vie onLoad de chaque page du mini programme, un document.body.appendChild
indépendant sera créé et défini comme variable globale, puis sa fonction document
correspondante sera appelée pour restituer chaque page indépendamment. render
从上面的小程序运行时原理来看,其性能相比原生是存在一定差距的,这主要由以下几个方面造成:第一:逻辑层运行完整的 Rax + 通过模拟 DOM/BOM API 处理 VDOM 并生成 setData 数据,需要消耗更多的计算时间;第二,相比原生小程序需要传递更多 setData 数据,如果容器层数据序列化能力较弱,会大大增加数据传输耗时;第三,视图层通过自定义组件递归动态生成视图,而我们知道递归动作本身就是一个性能损耗点。此外,由于无法预先知晓用户需要绑定的属性和事件,自定义组件模板中只能将所有属性和事件预先绑好,这导致小程序运行过程中会触发很多无用的事件,进一步加重负担。经过我们的 benchmark 计算,在支付宝小程序平台上,运行时小程序框架(包括 Rax/Taro/Remax 等)与原生小程序存在约 40% 的性能差距。
Rax 小程序运行时发布后,经测试其性能相比其他运行时框架存在着较为明显的差距,于是我们启动了性能调优的专项计划。通过以下方面的重构,成功将 Rax 小程序运行时小程序的性能拉升至业界领先水平,与 Taro/Remax 基本处于同一水平线。
更新数据精确化。在旧版本中,setData 的数据是全量更新的,虽然有 dom 子树分割批量更新的设计,但是数据传输仍然存在大量冗余。重构版本中,Rax 增加了节点渲染判断,未挂载节点无须触发更新;将所有更新收拢至顶层 root 节点统一批量处理, 并且通过精确计算数据更新的 path,实现局部更新。比如某次更新节点的 class 属性时,setData 的数据可能是:
{ "root.children.[0].children.[1].class": "active"}复制代码
内置小程序组件无需维护其属性列表,而是根据用户传参直接赋值。旧版本中,我们维护了所有内置组件的属性,在获取属性值的时候均需要调用 domNode.getAttribute,具有一定性能开销。重构版本 Rax 直接根据用户传参给属性赋值,并将默认值设置的操作移至视图层 WXS/SJS 中处理。
更新 Décryptage et réflexion sur la solution dexécution de lapplet Rax 中的数据结构。经过梳理,Rax 移除了冗余的 tree 数据,重写了 getaElementById 等 API;重构了 attribute、classList 等类;使用了更符合场景需要的 Map/Set 等数据结构,提升了整体的数据处理性能。
渲染模板优化。在支付宝小程序中,Rax 使用 template 进行递归调用;在微信中,Rax 使用 template 调用 element 再调用 template 的形式以避免微信端递归调用 template 的层数限制。在模板中,我们尽量使用 template is 语法进行判断,减少 a:if/wx:if 条件判断,提升模板递归时的性能。
无论是出于旧有业务的迁移,或者是出于性能考虑,Rax 小程序运行时中都存在着混合使用的需求。目前,Rax 已经打通与小程序内置组件、小程序自定义组件、小程序页面、小程序插件混合使用的能力。这其中,使用小程序自定义组件是最为复杂的。
在 Rax 中使用小程序自定义组件,其引入路径需要与 usingComponents
保持一致(例如 import CustomComp from '../components/CustomComp/index'
)。 在编译阶段,Rax 工程使用 Babel 插件进行代码扫描,检测到 JSX 中使用的某个组件是小程序自定义组件(根据其引入路径是否存在同名 axml 文件)时,会将其使用到的属性和事件进行缓存,然后通过 webpack 插件动态生成至递归模板中。在运行时中的创建节点阶段,通过查询缓存判断节点是否为自定义组件。若是自定义组件,则其渲染数据中会插入缓存中的属性,并且绑定事件至该自定义组件实例。
通过 Rax 小程序编译时方案产出的组件,从使用形态上来说,可以直接视为小程序自定义组件。而 Rax 工程加强了运行时与编译时的联系,当在 Rax 小程序运行时中使用编译时组件 npm 包时,用户无需引入组件的具体路径,只需像使用普通组件时一样引入,Rax 工程将自动根据该组件 package.json
中是否存在 miniappConfig
字段来判断其是否为一个 Rax 多端组件,然后直接使用其编译时的组件实现。
Rax est la seule solution de développement de petits programmes du secteur qui prend en charge à la fois les moteurs de compilation et d'exécution. Sa capacité à mélanger deux moteurs permet d'atteindre parfaitement un équilibre entre performances et développement. efficacité. À l'avenir, Rax mettra en œuvre une méthode d'utilisation mixte à double moteur plus flexible, telle que la prise en charge de la désignation d'un composant à compiler avec le moteur de compilation dans un seul projet, offrant ainsi une plus grande flexibilité à l'entreprise.
Ce qui précède est l'analyse principale de la solution d'exécution de l'applet Rax. La solution d'exécution résout les limitations de syntaxe inhérentes à la solution de compilation, mais il existe également des contraintes de performances évidentes. On peut dire qu'au stade actuel de 2020, il n'existe toujours pas de solution miracle pour le développement de mini-programmes. Peut-être que la fusion des deux moteurs du mini-programme Rax sera une solution optimale dans une gamme relativement large. Personne ne peut dire jusqu'où peuvent aller les mini-programmes qui vont à l'encontre des normes. Les développeurs devront encore faire face à divers problèmes pendant un certain temps encore. Du point de vue d'un petit cadre de développement de programmes, j'espère seulement que tous les développeurs pourront choisir le cadre le plus approprié pour eux-mêmes et terminer le développement de petits programmes rapidement et efficacement.
Recommandations d'apprentissage gratuites associées : Tutoriel de développement d'applets WeChat
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!