ホームページ  >  記事  >  WeChat アプレット  >  Rax アプレット ランタイム ソリューションの復号化と考察

Rax アプレット ランタイム ソリューションの復号化と考察

coldplay.xixi
coldplay.xixi転載
2020-11-04 17:45:373074ブラウズ

WeChat ミニ プログラム開発チュートリアルこのコラムでは、Rax ミニ プログラム ランタイム ソリューションを紹介します。

Rax アプレット ランタイム ソリューションの復号化と考察

2020 年 3 月に、コンパイル時スキームをサポートした後、Rax アプレットは実行時スキームをサポートするバージョンをリリースしました。今のところ、Rax はコンパイル時と実行時の両方のソリューションをサポートする業界で唯一の小規模プログラム開発フレームワークです。この記事では、Rax アプレット ランタイム ソリューションの原理と私たちの考え方を紹介します。

コンパイル時ソリューションを確認する

実行時ソリューションを紹介する前に、コンパイル時ソリューションとは何かを確認しましょう。名前が示すように、コンパイル時ソリューションはコンパイルに重点を置いており、代表的なフレームワークは Taro v2.x です。静的コンパイルを通じて JSX をミニ プログラムのテンプレート言語 (WXML/AXML など) に変換し、軽量のランタイム JS コードでそれを補完して、ミニ プログラムのライフ サイクルと React のライフ サイクルの違いを平滑化します。ユーザーは使い慣れた React DSL を使用して小さなプログラムを開発できます。 Rax のコンパイル時スキームの原理は、Taro v2.x の原理と似ています。実装の詳細については、以前の記事「Rax からミニ プログラムへのリンクの原理の分析 (1)」および「ミニ プログラムへのリンクの原理の分析」を参照してください。 Rax Mini プログラムのコンパイル スキーム。ランタイム ソリューションは、コンパイル時ソリューションとは異なり、静的コンパイルに依存せず、実行時のレンダリング機能の実装に重点を置いているため、構文の制限がほとんどないことが最大の特徴です。ランタイム ソリューション実装の原則を見てみましょう。

誕生の基本

ミニ プログラムの基礎となる実装は、実際には Web テクノロジに基づいていますが、開発者レベルで反映されると、Web とはまったく異なります。ミニ プログラムでは、ロジック層とビュー層が分離されています。ロジック層はビュー層にデータを渡し、独自の setData メソッドを通じてレンダリングをトリガーし、ビュー層はイベントを通じてロジック層のコードをトリガーします。そのアーキテクチャは以下に示すとおりです。 Web 開発と比較すると、開発者は JS を使用してブラウザーが提供する DOM/BOM API を呼び出し、コンテンツを自由に操作およびレンダリングできます。ミニ プログラムのアーキテクチャはより閉鎖的で安全ですが、Web コードを直接実行できないことも意味します。ミニ番組で。

Rax アプレット ランタイム ソリューションの復号化と考察

最新のフロントエンド フレームワーク (React/Vue) の場合、基本的に最下層は DOM API を呼び出してビューを作成します。ミニプログラムのビューレイヤーテンプレートは開発者が事前に記述する必要があるため、ミニプログラムでは動的にDOMを作成する方法は許可されていません。ただし、ミニ プログラムのカスタム コンポーネントの「自己参照」機能により、DOM を動的に作成するためのブレークスルーが開かれます。いわゆる自己参照とは、カスタム コンポーネントがそれ自体を子ノードとして使用することをサポートすることを意味します。これは、再帰参照を通じて、任意のレベルおよび数の DOM ツリーを構築できることを意味します。

たとえば、小規模プログラムのカスタム コンポーネント要素の WXML テンプレートが次のとおりであるとします。

<view>  <block>      <element></element>  </block></view><text>  {{r.content}}</text>复制代码

要素はテンプレート内で再帰的にそれ自体を参照し、条件判断によって再帰を終了することに注意してください。次に、ロジック層が次のデータを setData 経由で渡すと:

{
  "nodeId": "1",
  "tagName": "view",
  "children": [
    {
      "nodeId": "2",
      "tagName": "text",
      “content”: “我是?"
    },
    {
      "nodeId": "3",
      “tagName": "text",
      "content": "rax"    }
  ]
}复制代码

最終的なビューは次のようになります:

<view>
  <text>我是</text>
  <text>rax</text></view>复制代码

このようにして、動的にレンダリングする機能を巧みに実装しました。 WXML テンプレートが修正された場合、受信した setData データに基づくビュー。そしてこれがランタイム ソリューション誕生の基礎となります。

基本原則

Rax のランタイム ソリューションは、WeChat によって正式に開始されたミニ プログラムと Web エンド用の同型ソリューションである kbone から派生しています。 kbone の設計原則は公式 Web サイトの紹介を参照してください。簡単に要約すると、論理層で DOM/BOM API をシミュレートし、これらのビュー作成メソッドを VDOM ツリーの維持に変換し、それを対応する setData データを取得し、最後にプリセット テンプレートを使用して実際のビューを再帰的にレンダリングします。 DOM APIからVDOMツリーの維持までの処理の基本原理は複雑ではなく、createElement/appendChild/insertBefore/removeChildなどが基本的なデータ構造操作に相当します。

Rax に詳しい学生は、クロスターミナルをサポートするために、Rax にはドライバー設計があることを知っておく必要があります。実際、小さなプログラム用に別のドライバーを作成し、上記の原則に基づいてそのインターフェイス API を実装できます。しかし、私たちの最終的な選択は、下位レベルのシミュレートされた BOM/DOM API を通じてレンダリング メカニズム全体を完了することでした。これを行うための考慮事項は、まず、最速のソリューションである kbone 開発に基づいています。ミニ プログラム側のドライバーは、Web 側のドライバー dom を再利用するだけで済みます。結局のところ、基礎となる document およびwindow 変数はシミュレートされています。第 2 に、開発者に Web に近い開発エクスペリエンスを提供したいためです。このソリューションは、開発者が JSX の使用に加えて、BOM/DOM API を直接使用してビューを作成できることを意味し、より柔軟になります。市場にあるすべてのミニ プログラム ランタイム フレームワークを検討します。Remax は、react-reconciler (前述の Rax ミニ プログラム ドライバーの設計と同様) を介して VDOM レイヤーのミニ プログラムと直接インターフェイスしますが、kbone と Taro 3.0 は両方ともシミュレーションを使用することを選択します。 . レンダリングを実装するための Web 環境。これはフレームワーク開発者の設計意図にも関係しており、意見は様々です。 Rax アプレット ランタイム ソリューションの基本的な概略図は次のとおりです。 Rax 小程序运行时基本原理图

イベント システム

Rax アプレット ランタイムでは、DOM/BOM API をシミュレートするライブラリは Rax アプレット ランタイム ソリューションの復号化と考察 です。サポートする API は次のとおりです: Rax アプレット ランタイム ソリューションの復号化と考察

レンダリング データの処理に加えて、もう 1 つの重要な点はイベント システムです。これは、EventTarget 基本クラスを通じて完全なイベント ディスパッチ メカニズムを実装します。論理層 DOM ノードはすべて EventTarget から継承し、一意の nodeId を通じて独自のバインディング イベントを収集します。ビュー レイヤー テンプレートの各組み込みコンポーネントは nodeId にバインドされ、すべてのトリガー可能なイベントをリッスンします。たとえば、単純なビュー タグは、bindtap/bindtouchstart/bindtouchend およびその他のイベントをバインドします。イベントがトリガーされると、ターゲット ノード ID が event.currentTarget.dataset.nodeId を通じて取得され、ノード上でユーザーによってバインドされた対応する関数がトリガーされます。

エンジニアリング設計

Rax ミニ プログラム ランタイムのメイン プロジェクト プロセスは Rax Web の設計に従っており、Web 側の Webpack によってパッケージ化された JS バンドルはミニ プログラム ランタイムで再利用できます。 Rax アプレット ランタイム ソリューションの復号化と考察 でシミュレートされたウィンドウ変数とドキュメント変数をプラグインを通じてバンドルに挿入し、固定ミニ プログラム プロジェクト スケルトンを生成して、JS バンドルを app.js にロードします。プロジェクト全体の構造を次の図に示します。 Rax 小程序运行时工程结构

MPA または SPA ?

上記のアーキテクチャは、段階的な進化の結果です。最初は、webpack のマルチエントリ モードを使用してランタイム アプレット コードをパッケージ化しました。つまり、各ページはエントリとして独立してパッケージ化されました。これにより、アプレットはより MPA のように動作します。これが引き起こす問題は、ページ間で共通に依存するコードが同じメモリ内で実行されず、ネイティブ アプレットのパフォーマンスと一致しないことです。この違いにより、プロジェクトのパッケージ化モデルを変更するという最終決定が下されました。 Rax ランタイム アプレットの現在のバージョンは SPA の形式により準拠しており、すべてのビジネス コードが JS ファイルにパッケージ化されています。

ミニ プログラムの実行中に、Rax プロジェクトの入り口の rax-app パッケージのリンクを変更しました。初期化中に、 render 関数はルート ノード (document.createElement) を作成し、対応する Rax コンポーネントをそれにマウントし、ルート ノードを本体ノード (document.createElement) に追加します。 body.appendChild)。ミニ プログラムの各ページの onLoad ライフ サイクル中に、独立した document が作成されてグローバル変数として設定され、対応する 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 中处理。

  • 更新 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 は、コンパイル時エンジンとランタイム エンジンの両方をサポートする業界で唯一の小規模プログラム開発ソリューションです。デュアル エンジンを混合する機能により、パフォーマンスと開発のバランスを完全に達成できます。効率。将来的には、Rax は、単一プロジェクト内でコンパイル時エンジンでコンパイルされるコンポーネントの指定をサポートするなど、より柔軟なデュアルエンジン混合使用方法を実装し、ビジネスに高い柔軟性を提供します。

概要

上記は、Rax アプレット ランタイム ソリューションの原理分析です。実行時ソリューションは、コンパイル時ソリューションに固有の構文制限を解決しますが、明らかなパフォーマンス制約もあります。 2020 年の現時点では、ミニプログラム開発にはまだ特効薬はないと言えますが、おそらく Rax ミニプログラムのデュアルエンジンの融合が、比較的広い範囲での最適解となるでしょう。標準に反するミニプログラムがどこまでできるかは誰にもわかりませんし、開発者は今後もしばらくの間、さまざまな問題に直面しなければなりません。小規模プログラム開発フレームワークの観点から、開発者の皆様がご自身に最適なフレームワークを選択して、小規模プログラムの開発を迅速かつ効率的に完了できることを願うばかりです。

関連する無料学習の推奨事項: WeChat ミニ プログラム開発チュートリアル

以上がRax アプレット ランタイム ソリューションの復号化と考察の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。