ホームページ  >  記事  >  eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

青灯夜游
青灯夜游転載
2022-08-18 11:27:454817ブラウズ

JavaScript で記述できるアプリケーションはすべて、最終的には JavaScript で記述されることになります。同様に、ミニ プログラムを使用して実装できる製品は、最終的にはミニ プログラムを使用して実装されます。では、小さなプログラムを開発するにはどうすればよいでしょうか?次の記事は、電子商取引フロントエンド チーム向けの 5 年間の小規模プログラム開発の経験 (Wanzi 原則と最適化のヒント) を要約して共有しています。

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

1. デュアル スレッド アーキテクチャについて議論する

WeChat ミニ プログラムの基礎となる設計に関する質問

  • デュアル スレッド モデルとは正確には何ですか?
  • ビューとロジックを分離するにはどうすればよいですか?
  • なぜ WXML や WXSS のような奇妙な構文を使用するのでしょうか?
  • 危険な操作 API をブロックするにはどうすればよいですか?
  • コミュニケーション方法と、データ駆動型ビューの更新を実装する方法は?
  • デュアルスレッド モデルの欠点は何ですか?

1. モデルの構成

1) 従来のブラウザ プロセスとスレッド モデルの問題

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

パフォーマンスの問題

レンダリング スレッドと JS エンジン スレッドは相互に排他的であり、ブロッキングの問題があります。長期にわたる JS スクリプトの実行は直接影響 UI ビューへのレンダリングによりページラグが発生する

セキュリティ問題

危険な HTML タグ (a、script) および JS API (Function、eval、DOM API)攻撃者にとって、ページのコンテンツを改ざんしたり、ユーザー情報を不正に取得したりすることが簡単です。

解決策

アプレットは、ビューの表示とロジックを組み合わせるためにデュアル スレッド モデルを使用しています。処理は 2 つのスレッドで別々に実行されます HTML タグはモデル内でカプセル化されます 開発者はネイティブ タグを直接呼び出すことはできません JS 本来の危険なロジック操作 API 機能もブロックされ、関与する通信アクションは仮想 DOM 更新のみをトリガーできます(データドリブン ビュー) 中間層によって提供される API を介して

#2)、ミニ プログラム デュアル スレッド モデル

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】ビュー層とロジック層の機能は、WeChat クライアントに組み込まれているミニ プログラム基本ライブラリの JS ファイルを通じて提供されます。

WAWebview.js

ビューの基本的な API 機能を提供します。コンポーネント システムの完全なセットと Virtual Dom (仮想 DOM) の関連実装が含まれます

WAService.js

ロジック層に基づいた API 機能を提供し、さまざまな操作の API を開発者に公開します

3)、クライアント エンジンの基盤となる実装

実行環境が異なると、スクリプト実行環境とコンポーネント レンダリングの環境が異なり、パフォーマンスも異なります。

    iOS、iPadOS、および Mac OS では、アプレット ロジック層の JavaScript コードは
  • JavaScriptCore

    で実行され、ビュー層は WKWebView によってレンダリングされ、環境はiOS 14、iPad OS 14、Mac OS 11.4 など。

  • Android では、アプレット ロジック層の JavaScript コードは
  • V8

    で実行され、ビュー層はMobile Chromium に基づいています コアは WeChat 自社開発 XWeb エンジン (過去の X5 から自社開発 XWeb エンジン) によってレンダリングされ、ビュー層は Mobile Chrome カーネルに基づいてレンダリングされ、公式開示によると、将来的には、ロジック層も V8 から分離され、カスタマイズされた Customized XWeb Worker スレッドを使用することになります。つまり、Web Worker スレッドをアプレットの論理層としてカスタマイズすることになります。 参考リンク)

  • Windowsでは、アプレットロジック層のJavaScriptとビュー層はChromiumカーネルを使用します
  • 開発ツールでは、アプレット ロジック層の JavaScript コードは
  • NW.js

    で実行され、ビュー層は Chromium WebView

によってレンダリングされます。 2. ビューレイヤー

1)、ミニ プログラム コンポーネント システム

ミニ プログラムには 3 種類のコンポーネントが含まれます: 組み込みコンポーネント、カスタム コンポーネント、コンポーネント、ネイティブ コンポーネント

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】##2)、ミニ プログラム コンポーネント構成フレームワーク

##1、Web コンポーネント Web コンポーネント

は、カプセル化された関数とカスタマイズされた要素をブラウザーで作成する機能で、3 つの主要なテクノロジで構成されます
  • #カスタム要素カスタム要素とその動作を定義できる一連の JavaScript API。ユーザー インターフェイスで必要に応じて使用できます

  • ##シャドウ DOM カプセル化された「シャドウ」DOM ツリーを要素 (メイン ドキュメント DOM とは別にレンダリングされる) にアタッチし、その関連関数を制御するための JavaScript API のセット。この方法で要素の機能をプライベートに保つことで、ドキュメントの他の部分との競合を恐れることなく、要素のスクリプトやスタイルを設定できるようになります。

  • #HTML テンプレート (HTML テンプレート)

#テンプレート要素とスロット要素を使用すると、レンダリングされたページに表示されないマークアップ テンプレートを作成できます。これらは、カスタム要素構造の基礎として何度も再利用できます

2. Exparser フレームワーク
Exparser は、WeChat ミニ プログラムのコンポーネント編成フレームワークであり、ミニ プログラム ベース ライブラリに組み込まれており、プログラムのさまざまなコンポーネントに対する基本的なサポートを提供します 組み込みコンポーネントやカスタム コンポーネントを含むミニ プログラム内のすべてのコンポーネントは、Exparser によって編成および管理されます。

ミニ プログラムでは、WXML の構築からページの最終ノード ツリー、createSelectorQuery 呼び出し、カスタム コンポーネント機能など。

Exparser は、ノード属性、イベント バインディングなどを含む、ページ全体のノード ツリーに関連する情報を維持します。これは、以下と同等です。 Shadow DOM 実装の簡略化されたバージョン

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

3. エクスパーサー機能
    ##Shadow DOM モデルに基づく: モデルは非常に類似しています。 Web コンポーネントの Shadow DOM に追加されますが、ブラウザのネイティブ サポートに依存せず、他の依存ライブラリはありません。実装中に、小規模なプログラム コンポーネント プログラミングをサポートするために他の API も追加されます
  • # 純粋な JS 環境で実行可能: これは、ロジック層にも特定のコンポーネント ツリー構成機能があることを意味します (コンポーネントのレンダリングで使用されます)
  • #効率的で軽量: 優れています特に多数のコンポーネント インスタンスが存在する環境で優れたパフォーマンスを実現し、同時にコード サイズも小さくなります

  • #4. Exparser コア メソッド

  • registerBehavior
コンポーネントが継承するようにコンポーネントのいくつかの基本的な動作を登録します

registerElement コンポーネントを登録します。対話するインターフェイスは主にプロパティとイベントです

コンポーネントの作成

ミニ プログラムの基本ライブラリには Page と Component の 2 つのコンストラクターがあり、アプレットを起動すると、プロパティ、データ、メソッドなどの定義されたフィールドが表示されます。ページを初期化するときに、Exparser はページ ルート コンポーネントのインスタンスを作成し、使用される他のコンポーネントもそれに応じてコンポーネント インスタンスを作成します (これは再帰的なプロセスです)

5。ページとコンポーネントのプロセス

上図から明らかなように、ミニプログラムのページレンダリングとコンポーネントレンダリングでは通信方法に違いがあることがわかります。このうち、ページレンダリングにおける VDOM の生成と diff はビュー層で完了し、ロジック層はレンダリング層の更新ロジックをトリガーするためのデータ送信のみを行います。コンポーネントのレンダリングでは、ロジック層とビュー層が共同で一組のVDOMを維持する必要があり、その方法としては、コンポーネントの初期化時にロジック層にコンポーネントのVDOMを構築し、ビュー層に同期させる方法があります。後続の更新操作では、最初にロジック層で古い VDOM と新しい VDOM の差分が実行され、その後、差分後の結果のみが伝達され、VDOM の直接更新とレンダリングのためにビュー層に渡されます。これを行う最大の利点は、DOM レベルへのビュー更新通信の粒度を制御できることです (データの変更が必ずしもビューの更新をもたらさない場合があるため)、最終的に変更される DOM のみが更新されます。データ レベルの更新がより正確になり、不必要な通信コストが回避され、パフォーマンスが向上します。

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】3)、ミニ プログラム ネイティブ コンポーネント

1. ネイティブ コンポーネントの利点

機能を拡張します。ウェブ ###。たとえば、入力ボックス コンポーネント (input、textarea) には、キーボードをより適切に制御する機能があります。
  • エクスペリエンスが向上し、WebView のレンダリング作業も軽減されます。たとえば、マップ コンポーネントなどのより複雑なコンポーネントのレンダリング作業は WebView スレッドを占有せず、ネイティブ処理のためにより効率的なクライアントに引き渡されます。

  • レンダリング パフォーマンスの向上、setData、データ通信、再レンダリング プロセスをバイパスします。たとえば、キャンバス コンポーネント (キャンバス) は、豊富な描画インターフェイスのセットを直接使用できます。描く。

  • 2. ネイティブ コンポーネントの作成プロセス

    コンポーネントが作成された後、DOM ツリーに挿入され、プレースホルダー要素がレンダリングされ、ブラウザ カーネルはすぐにレイアウトを計算します。この時点で、ページに対するコンポーネントの位置 (x、y 座標)、幅、高さを読み取ることができます。
  • #コンポーネントは、クライアントが幅と高さに応じて同じ位置にネイティブ領域を挿入することをクライアントに通知し、クライアントはこの領域にインターフェイスをレンダリングします

  • ##位置または幅と高さが変更されると、コンポーネントは対応する調整を行うようにクライアントに通知します
  • ##3. ネイティブ コンポーネントのレンダリング制限

  • ## 一部の CSS スタイルはネイティブ コンポーネントに適用できません
#階層の問題 (ネイティブ コンポーネントは最上位レベルであり、WebView レイヤーのコンポーネントをカバーします)
  • ## 解決策
  • カバービュー コンポーネントとカバー画像コンポーネントを使用して、ネイティブ コンポーネントをカバーします (機能が制限され、柔軟性がありません)

同じレイヤーのレンダリング (特定の技術的手段を通じてネイティブ コンポーネントを WebView の同じレベルに直接レンダリング)

  • 4)、同じレイヤーにネイティブ コンポーネントをレンダリング
  • 1. iOS システムの実装原理
#アプレットの iOS 側の同層レンダリングは WKChildScrollView をベースに実装されており、ネイティブ コンポーネントがアタッチされた後、直接マウントされます。事前に作成された WKChildScrollView コンテナへ

Principle Analysis

WKWebView は、内部でのレンダリングに階層化アプローチを使用します。WKWebView は、WebKit によって生成された合成レイヤー (合成レイヤー) をレンダリングします。カーネルを iOS 上の WKCompositingView コンポーネントに統合しますが、コンポジション レイヤー DOM ノードと 1 対 1 のマッピング関係はありません (カーネルは通常、複数の DOM ノードを 1 つのコンポジション レイヤーにマージします)。

WKChildScrollView: DOM ノードの CSS プロパティが overflow:scroll に設定されている場合 (下位バージョンでは同時に -webkit-overflow-scrolling:touch を設定する必要があります)、WKWebView はWKChildScrollView を生成します (iOS での WebView スクロールをよりスムーズにするために、WebView でのスクロールは実際には実際のネイティブ スクロール コンポーネントによって実行され、WebKit カーネルはすでに他の DOM ノードとの間の階層関係を処理しています)。 WKChildScrollView と DOM ノードの間には 1 対 1 のマッピング関係があります。

作成プロセス

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

DOM ノードを作成し、その CSS プロパティをオーバーフローに設定します: スクロールと- webkit-overflow-scrolling: touch

DOM ノードに対応するネイティブ WKChildScrollView コンポーネントを見つけるようにクライアントに通知します
  • ネイティブ コンポーネントをマウントしますWKChildScrollView ノードはその子 View
  • として機能します。上記のプロセスを通じて、アプレットのネイティブ コンポーネントが WKChildScrollView
  • 2 に挿入されます。 Android システムの実装原則
  • WebPlugin はブラウザ カーネルのプラグイン メカニズムであり、ミニ プログラムの Android 側での同じレイヤのレンダリングは、実装された

  • 原則に基づいています。分析
embed タグは HTML5 の新しいタグで、埋め込みコンテンツ (プラグイン、メディアなど) を定義するために使用されます。 ). 形式は PDF、Midi、Wav、MP3 など、Chrome での閲覧が可能です ブラウザ上の PDF プレビューは、embed タグに基づいて実装されます。

Chromium カーネル拡張機能と組み合わされた embed タグに基づいています。Chromium は、WebPlugin メカニズムをサポートしています。WebPlugin は、ブラウザ カーネルのプラグイン メカニズムです。主に、embed タグを解析して記述し、ネイティブのレンダリングに使用されます。 WebView 側で埋め込み DOM ノードを作成し、コンポーネント タイプを指定します

Chromium カーネルは WebPlugin インスタンスを作成し、RenderLayer を生成します

Android クライアントは、対応するネイティブ コンポーネントを初期化します

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】Android クライアントは、ステップで作成した RenderLayer にバインドされた SurfaceTexture にネイティブ コンポーネントの画像を描画します2

RenderLayer をレンダリングするように Chromium カーネルに通知します

  • Chromium は埋め込みノードをレンダリングし、画面に表示します

  • 5)、レイヤー コードのコンパイルを表示
  • WeChat 開発者ツールには、バイナリ WXML および WXSS コード ファイル コンパイラが組み込まれており、コンパイラは WXML および WXSS コード ファイル リストを受け入れます。処理後、JavaScript コード

  • 1 と WXSS コード ファイル
  • wcsc コマンド ツールの実行を出力します。 JS ファイルを生成する WXSS 製品
  • JS ファイルにはサイズ単位 rpx を追加する変換メソッドが含まれており、デバイスの画面に応じて使用できます。幅は px 単位に適応的に計算されます
  • #setCssToHead メソッドを提供して、変換された CSS コンテンツを HTML テンプレートの先頭に追加します

eval メソッドの実行この JS ファイル文字列でスタイル インジェクションが完了します

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

#2. WXML コード ファイル

WCC コマンド ツールの実行プロセス

  • wcc は WXML をコンパイルして JS ファイルを生成します。product

  • JS ファイルには $gwx メソッドが含まれ、WXML ファイルのパスを受け取り、実行後にgenerateFunc メソッドを生成し、generateFuncReady イベントをトリガーします。

  • generateFunc メソッドは、レンダリング関数と同様に、仮想 dom の生成に使用される動的データ データを受け取ります

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

##3. 論理層

1)、論理層にはコンテンツが含まれます

#JS コード実行環境を提供します
  • はウィンドウ オブジェクトです。モジュール インターフェイスの追加には定義が必要です。
  • #Page、App、getApp およびその他のインターフェイスを提供します。

  • API メソッドを以下に提供します。 wx グローバル オブジェクト、ネットワーク、メディア、ファイル、データ キャッシュ、場所、デバイス、インターフェイス、インターフェイス ノード情報およびいくつかの特別なオープン インターフェイス

  • 2)、JS コード実行環境

JSCore 構成 (

iOS

Android)1.JSVirtualMachine

It VM 環境をインスタンス化する JS コードを実行するには、実行する必要がある JS が複数ある場合、複数の VM をインスタンス化する必要があります。また、GC 問題が発生しやすいため、これらの VM は相互に対話できないことに注意してください。

2. JSContext

JSContext は、JS コードのコンテキスト オブジェクトです。 Webview のウィンドウ オブジェクトに相当します。同じ VM 内で、異なる Context

3、JSValue

WASM と同様に、JsValue は主に JS データ型と Swift または Java データ マッピングを解決するために使用されます。タイプ間。つまり、JSContext にマウントされたコンテンツはすべて JSValue 型です。Swift と Java は、内部的に JS と JS の間の型変換を自動的に実装します。

4, JSExport

は、ネイティブ インターフェイスを公開するために使用される JSCore のプロトコル。簡単に言うと、Nativeの関連するプロパティやメソッドをプロトタイプオブジェクトのメソッドやプロパティに直接変換します3.モジュール仕様の実装

Passed define はモジュールを定義し、そのモジュールが使用できる他のモジュール (ウィンドウ、ドキュメントなど) を制限します。define メソッドは、すべての JS コード ロジックを「パス-モジュール」キーと値のペアの形式でグローバル変数に格納することによって実装されます。

eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

##モジュールを適用するには、require を使用します。モジュールを使用する場合のみ、 require、module、exports を入力すると、コード内で読み取られる他の変数はすべて未定義になります。これは、一部のブラウザ環境オブジェクトがミニ プログラムで取得できない理由でもあります。1eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

  • これは実際には典型的なモジュール読み込みのアイデアであり、Webpack がモジュールをパッケージ化する方法と非常によく似ています。 WAService.js ファイル ビュー層とロジック層の基本的な API 機能を提供することに加えて、2 つのスレッド間で通信する機能も提供します。

アプレット ロジック層とレンダリング層の間の通信は次のようになります。ネイティブ (WeChat クライアント) によって行われます。転送の場合、論理層はネットワーク リクエストを送信し、ネイティブを介して転送も行います1eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

1)、および基礎となる実装

いくつかのエンドのさまざまな実装は、最終的には開発者が

1 を呼び出せるように、WeiXinJSBridge などの互換性レイヤーにカプセル化されます。iOS 側

ビュー レイヤーは、window.webkit.messageHandlers.NAME.postMessage および eval を通じて実装されます。 WKWebViewの。ロジック層は、グローバル ネイティブ メソッドを JavaScriptCore フレームワークに挿入します

2. Android 側

ビュー層とロジック層の実装原理は同じであり、どちらも WebView のウィンドウに送られます オブジェクトはネイティブ メソッド WeixinJSCore 実装に挿入されます。この WeixinJSCore は、JS 呼び出し用に WeChat によって提供されるインターフェイスです (ネイティブ実装)

3. WeChat 開発者ツール

通信に WebSocket を使用する

2) WeixinJSBridge モジュール オブジェクト

WeixinJSBridge は、ビュー層 JS とネイティブ、ビュー層とロジック層の間のメッセージ通信メカニズムを提供します。

invoke

:JS はネイティブ API

を呼び出します。

  • #on:JS がネイティブ メッセージをリッスンします

  • publish:ビュー レイヤーがメッセージをパブリッシュ

  • subscribe: ロジック層からのメッセージをサブスクライブします

  • ##5. デュアル スレッド アーキテクチャの欠陥と最適化

    1) デュアルスレッド アーキテクチャの欠陥

      DOM を柔軟に操作してより複雑な効果を実現できない
    • パーツとネイティブ コンポーネント 関連するビューには使用制限があります。たとえば、WeChat のスクロールビューにはテキストエリアを含めることはできません
    • #ページ サイズと開いているページの数は制限されています
    • #分離する必要があります 開発適応、既存のコード リソースは再利用できません

    • #JSCore 内の JS ボリュームが比較的大きい場合、その初期化時間は影響を受けます

    • #データを送信するときは、シリアル化と逆シリアル化の時間消費を考慮する必要があります
    • ##2)、デュアルスレッド アーキテクチャの最適化
    • ##パフォーマンスのボトルネックが発生するこれは、WeChat 自体が解決に取り組んできた重要な問題でもあります。前述したように、アプレットは、新しい XWeb カーネルの Chromium カーネルを変更することで、ロジック層の実装をカスタム XWeb ワーカー スレッドに置き換えます。これにより、追加の V8 が不要になり、メモリ使用量が大幅に増加します。また、Chromium カーネルの Worker スレッドをベースとしているため、データ通信に関しては、元の通信メソッドである setData を PostMessage に置き換えて、より高性能な通信機能を実現するのが当然です
    • #3)、Alipay アプレットのデュアル スレッド アーキテクチャ
    ##さらに、Alipay アプレットの基礎となる実装についても学び、研究しました。 Alipay アプレットも同様のデュアル スレッド アーキテクチャ モデルを使用しており、UC が提供するブラウザ カーネルを使用することで、レンダリング層は Webview スレッドで実行され、ロジック層は別のスレッドを開始して Service Worker を実行します。ただし、Service Worker は MessageChannel API を介してレンダリング スレッドと通信する必要があるため、データ量が多くオブジェクトが複雑な場合には、パフォーマンスのボトルネックも発生します。

    したがって、Alipay アプレットは既存の JS 仮想マシン V8 を再設計し、最適化された分離モデル (最適化分離モデル、OIM) を提案しました。 OIM の主なアイデアは、スレッド実行環境とは何の関係もない JS 仮想マシン インスタンス内のデータとインフラストラクチャ、および不変または不変の JS オブジェクトを共有することで、JS レイヤーの論理的な分離を維持しながら、マルチインスタンス シナリオではメモリと電力消費のオーバーヘッドを節約できます。インスタンス間で共有される一部のデータは同期オーバーヘッドをもたらしますが、分離モデルでは、このソリューションによって共有されるデータ、オブジェクト、コード、および仮想マシン インフラストラクチャは不変または不揮発性であるため、競合はほとんど発生しません。

    新しい分離モデルでは、Webview の V8 インスタンスはローカル ランタイムであり、ワーカー スレッドの V8 インスタンスもローカル ランタイムです。ロジック層とレンダリング層が相互作用するとき、setData オブジェクトは共有ヒープ内に直接作成されます。レンダリング レイヤーのローカル ランタイムは、オブジェクトを直接読み取り、レンダリング レイヤーのレンダリングに使用できます。これにより、オブジェクトのシリアル化とネットワーク送信が削減され、起動パフォーマンスとレンダリング パフォーマンスが大幅に向上します。 。

    1eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】さらに、Alipay アプレットはホームページのオフライン キャッシュの最適化を実装しています。最初に前回保存したホームページ UI ページをレンダリングし、ユーザーにホームページを表示してから、引き続きフロントエンド フレームワークとビジネス コードを読み込みます。読み込みが完了すると、オフライン キャッシュされたホームページ UI とマージされ、動的なホームページがユーザーに表示されます。これは、WeChat アプレットの初期レンダリング キャッシュ スキームに非常に似ており、より過激です。 WebAssembly テクノロジーは、仮想 DOM のコア コードを再実装し、ミニ プログラムのページ レンダリングを改善するためにも使用されました。 [推奨関連ビデオ チュートリアル:

    Web フロントエンド

    ]

    6. デュアル スレッド モデル アーキテクチャの設計に関する考え方

    技術アーキテクチャは問題を解決するために生まれた優れた技術ソリューションは、設計者が開発効率、技術コスト、パフォーマンス エクスペリエンス、システム セキュリティの間でバランスとトレードオフを行う必要があるだけでなく、ビジネス トレンド、製品形式、ユーザーと密接に統合されている必要があります。要求

    #2. ランタイム メカニズムの詳細

    ##1. コード パッケージのダウンロード

    ##ミニ プログラムの開始時(コールド スタート)、WeChat は、ミニ プログラムのアイコン、名前、読み込みプロンプト アイコンを含む固定スタートアップ インターフェイスを表示します。

    この時点で、WeChat はバックグラウンドでいくつかのタスクを完了します。ミニ プログラム コード パッケージをダウンロードし、ミニ プログラム コード パッケージをロードし、ミニ プログラム ホームページを初期化します。

    開発者の観点から見ると、コード パッケージのサイズを制御すると、ミニ プログラムの起動時間を短縮できます。 1MB 未満のコード パッケージの場合、ダウンロード時間は 929ms (iOS) 1500ms (Android)

    # 以内に制御できます。最適化計画

    • メイン パッケージとサブパッケージのサイズを削減します

    • 合理的な割り当て、サブパッケージのプリロード ルール

    • 細かい分割、非同期の下請け

    2. ページ レベルの準備

    ミニ プログラムを開始する前に、WeChatミニプログラムのホームページを表示するためのページレベルを事前に用意します。ページ レベルを使用してページをレンダリングするときは常に、WeChat は事前に新しいページ レベルの準備を開始し、wx.navigateTo が呼び出されるたびに新しいページをできるだけ早く表示できるようにします。ビュー レイヤー ページのコンテンツは、pageframe.html テンプレートを通じて生成されます

    eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

    #ページ レベルの準備手順

    1eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

      最初の段階は、WebView を開始することです。iOS および Android システムでは、オペレーティング システムが WebView を開始するまでに少し時間がかかります。
    • ##第 2 段階は、WebView で基本ライブラリを初期化します。このとき、ページ レンダリングのパフォーマンスを向上させるために、基本ライブラリの内部最適化が実行されます。
    • 第 3 段階は、ミニ プログラムの WXML 構造と WXSS スタイルを挿入して、ミニ プログラムを作成します。 プログラムは、ページの初期データを受信した直後にページのレンダリングを開始できます (この段階は、ミニ プログラムが開始される前に実行できません)
    3. ページ コードの挿入と実行

    1)、グローバル変数の初期化

    ビュー レイヤーグローバル変数

    __wxConfig: これは、ページ、下請けページ、タブバー、その他の情報を含む、グローバル構成とページ構成によって生成された構成オブジェクトに基づいています
    • __wxAppCode__: なし-JS型開発者コード
    • JSON: JSON設定ファイルの内容
    • WXML: $gwx関数の実行結果は実行可能関数であり、実行後はVDOMオブジェクトが返されます。
    • WXSS: eval 実行スタイル関数の結果は実行可能関数です。実行後、スタイル タグが挿入されます
    論理層グローバル変数

    #__wxConfig: ビュー レイヤーと同様、下請けページ、タブバー、その他の情報は含まれません

      __wxAppCode__: ビュー レイヤーと同様、WXSS タイプのデータは含まれません
    • __wxRoute: 現在ロードされているページのパスを指すために使用されます
    • #__wxRouteBegin: ページの正しい登録をマークするために使用されます
    • __wxAppCurrentFile__: 現在ロードされている JS ファイルを指すために使用されます
    • __wxAppData: アプレットの各ページのデータ ドメイン オブジェクト
    • Component: カスタム コンポーネント コンストラクター
    • Behavior: カスタム コンポーネント動作コンストラクター
    • definePlugin: カスタム プラグイン-in コンストラクター
    • global: グローバル オブジェクト
    • WeixinWorker: マルチスレッド コンストラクター
    • #2)、基本ライブラリおよびビジネス コード JS ファイル インジェクション

    レイヤー コード インジェクションの表示

    wxml.js ファイルのインジェクトと実行 ($ gwx メソッドの定義) wxss.js ファイル (eval メソッド、app.wxss スタイル ファイルを追加)

      __wxAppCode__ 変数を追加
    1. eval メソッドを実行し、現在のページに挿入し、コンポーネント スタイル ファイルを参照します
    2. $gwx (現在のページ パス) を実行し、対応するメソッドを返して仮想 DOM を生成します
    3. ロジック層コード インジェクション

    JS ファイルをインジェクトして実行します(順序: other、babel、Component、Page、App) wxml.js ファイルをインジェクトして実行 ($gwx メソッドを定義)

    1. オンデマンド インジェクションと時間-消費インジェクション
    通常、ミニ プログラムが開始されると、スタートアップ ページが配置されているサブパッケージおよびメイン パッケージ (独立したサブパッケージを除く) 内のすべての JS コードがマージ インジェクションになります。基本ライブラリ バージョン 2.11.1 以降、

    オンデマンド インジェクションとタイムベース インジェクションが設定されており、アプレットは現在のページに必要なカスタム コンポーネントとページ コード、およびページで使用されないカスタマイズのみをインジェクトします。ページ。コンポーネントはロードおよび初期化されません

    3)、ロジック層のビジネス コードの実行

    4、データ通信とビューのレンダリング

    1eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

    1)、ページの初期レンダリング

    データ通信

    アプレットが開始または新規 ページが開かれると、ビュー レイヤーの初期レンダリングのために、ページの初期データ (データ) とパス、およびその他の関連情報がロジック レイヤーからビュー レイヤーに送信されます。

    ネイティブ レイヤーはこれらのデータをビュー レイヤーに直接渡し、同時に新しいページ レベルをユーザーに提示し、ビュー レイヤーはこのページ レベルでインターフェイスを描画します。

    #ビュー レイヤーが関連データを受信すると、ページ パスに従って適切な WXML 構造が選択されます。WXML 構造は初期データと結合されて、ページの最初のレンダリング結果が取得されます

    1eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

    ビュー レイヤーのコード インジェクションが完了し、ロジック レイヤーによって送信された初期データを受信した後、初期データとビュー レイヤーから取得したページ構造とスタイル情報を組み合わせて、ミニ プログラム フレームワークが作成されます。ミニ プログラムのホームページをレンダリングして表示します。ミニ プログラムの最初の画面は、ホームページ上で onReady イベントをトリガーします。

    初期レンダリング キャッシュをオンにすると、ロジック層の初期データに依存せず、レンダリング層のキャッシュ データを使用して最初のレンダリングを直接完了できるため、起動時間が短縮されます。 (onReadyイベントは事前に実行されます)。

    eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

    #ページの初期化時間は、ページの初期データ通信時間と初期レンダリング時間の 2 つの部分で大まかに構成されます。 このうちデータ通信時間は、論理層でのデータ整理開始からビュー層での受信完了までの時間を指し、データ量が64KB以下の場合は合計30ms以内に制御可能です。

    送信時間は一般にデータ量と正の相関関係があり、大きすぎるデータを送信すると、送信時間が大幅に長くなります。 したがって、

    送信データ量を削減するは、データ送信時間を短縮する効果的な方法です。

    初期レンダリング

    初期レンダリングは、ページが作成されたばかりのときに行われます。初期レンダリング中に、初期データが対応する WXML フラグメントに適用されてノード ツリーが生成されます。ノード ツリーは、開発者ツールの WXML パネルに表示されるページ ツリー構造であり、ページ内のすべてのコンポーネント ノードの名前、属性値、イベント コールバック関数、その他の情報が含まれています。最後に、ノードツリーに含まれる各ノードに従って、各コンポーネントがインターフェース上に順次作成されます。最初のレンダリングで取得されたデータと現在のノード ツリーは、再レンダリングのために保持されます。

    2eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

    このプロセス全体において、時間のオーバーヘッドは通常、ノード ツリー内のノードの総数に比例します。したがって、

    WXML のノード数を減らすと、初期レンダリングと再レンダリングにかかる​​時間のオーバーヘッドが効果的に削減され、レンダリングのパフォーマンスが向上します。

    2) データ レンダリングの更新

    最初のレンダリングが完了した後、開発者が setData を呼び出した後、ビュー レイヤはインターフェイスの更新を実行できます。

    setData 原則

    1. 対応する this.data の値を変更します (同期操作)

    属性名 (. と [ を含む) を解析します。 ]などのデータパスシンボル)、対応する階層構造を返し、対応するローカルデータの値を変更

    #
    {abc: 1} 中 abc 属性名 => [abc]
    {a.b.c: 1} 中 'a.b.c' 属性 => [a,b,c]
    {"array[0].text": 1} => [array, 0, text]
    ##2. ロジック層からビュー層へデータを送信(非同期操作)

    evaluateJavascript

    : ユーザーが送信したデータは送信用の文字列に変換する必要があり、同時に変換されたデータ内容は JS スクリプトに結合され、独立した Javascript に渡されます。 JS スクリプトを実行することで、両側の環境を統合します。

    再レンダリングの際、ロジック層は setData データをデータにマージし、レンダリング層はデータと setData データを適用します。 WXML フラグメントにコピーして、新しいノード ツリーを取得します。次に、新しいノード ツリーと現在のノード ツリーを比較して、どのノードを更新する必要があるか、どのノードを追加または削除する必要があるかを取得できます。最後に、古いノード ツリーは、次回の再レンダリングのために新しいノード ツリーに置き換えられます。 2eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

    現在のノード ツリーと新しいノード ツリーを比較する場合、setData データの影響を受けるノード属性が比較されます。したがって、不要なセットデータを削除し、setData 内のデータ量を減らすことも、このステップのパフォーマンスの向上に役立ちます。

    3)、ユーザー イベント通信

    ビュー レイヤーは、クリック イベント、タッチ イベント

    などのユーザー イベントを受け入れます。

    ユーザー イベントの通信は比較的単純です。ユーザー イベントがトリガーされ、関連するイベント リスナーをトリガーする必要がある場合、ビュー層はその情報をロジック層にフィードバックします。

    この通信処理は非同期であるため、一定の遅延が発生しますが、この遅延時間は送信データ量にも相関しており、データ量が64KB未満の場合は30ms以内となります。

    遅延時間を短縮するには、主に 2 つの方法があります。2eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

    不要なイベント バインディング ( WXML のバインドとキャッチ) を削除します。通信データ量と頻度の削減
    • #イベントをバインドする場合、target と currentTarget のデータセットを送信する必要があるため、ノードの data prefix 属性に大きすぎるデータを配置しないでください

    三、小程序基建和优化方案实践

    1、小程序性能优化

    1)、代码分包

    1、合理的分包和分包预加载策略

    主包内容

    Tab页(系统要求)、业务必要页面(错误兜底页、登陆授权页等),其余文件都以业务模块或者页面的维度,拆分成各自的分包

    分包预加载

    据用户的实际使用场景,预测下一跳的页面,将可能性最高的场景设置为预加载分包(可以参照业务埋点数据),例如:进入电商首页后,需要对会场和商详页的分包进行预加载

    2、组件分包分发

    实现思路

    小程序不支持主包引用分包代码,只能在分包中引用主包代码,所以把公共使用的组件代码放在主包目录中,但这些公共组件未必在主包所属的页面中会被引用,可能只是在分包页面中被多次引用,这样使得主包中代码体积越来越大,用户首次加载速度变慢。

    将主包页面不依赖的公共组件分别分发到依赖它们的分包目录中,虽然分包各自的体积会有所增大,但主包体积会有显著下降

    实现原理

    将所有需要分发的组件放置主包指定目录中,并添加配置文件,说明组建文件分发信息。在开发时用 gulp 任务监听单个文件变化、在构建时递归遍历所有组件,将其复制到配置文件中指定的子包路径目录中。

    目标文件在复制之前,都先要将文件内的依赖路径进行更新,使其在子包中运行时也能引用成功。针对不同类型的文件,采取不同的依赖分析手段。

    • JS 文件:使用 babel.transformFile 修改依赖引用地址

    • WXSS 文件:使用 postcss.plugin('transform-wxss') 处理依赖的 @import 导入样式文件地址

    • WXML 文件:使用 require('htmlparser2').Parser 来转换内部 wxs、template(import 和 include 导入)依赖的引用地址

    异步分包

    小程序基础库版本 2.17.3 及以上开始支持分包异步化,即可以在分包之间互相引用,这个能力可以快速取代我们自己的组件分发方案,而且优化效果更佳,可以将分包中公共依赖的代码部分打成新的分包,在使用时异步按需引入,能力与 Web 端的异步组件类似,但这个方案在生产环境的稳定性有待验证。

    2)、setData 优化

    实现思路

    合并 setData 调用,将其放在下个时间片(事件循环)统一传输,降低通信频率

    实现原理

    需要先将逻辑层 this.data 进行更新,避免前后数据不一致造成逻辑出错。将需要传送至视图层的 data 进行整合,在 nextTick 中调用原生的 setData 统一进行传送,可以有效降低通信频率,并且在传送前手动做一次与 this.data 的 diff 操作,降低通信体积

    1. 降低频率

    const nextTick = wx.nextTick ? wx.nextTick : setTimeout; // 小程序里的时间片 API

    2. 减少体积

    参考京东 Taro 中 diff 的实现,对基本、数组、对象等不同类型进行处理,最终转换为 arr[1]、x.y 这样的属性路径语法,减少传输信息量

    3)、Storage API 重封装

    实现思路

    onLaunch、onLoad 等生命周期函数中存在大量对微信 Storage 的同步调用(使用 Sync 结尾的API),这些操作涉及JS与原生通信,同步等待耗时过久,推迟页面 onReady 触发即用户可交互时间,影响用户体验。直接改为异步操作又存在业务代码改动量较大的问题,存在一定风险,大量的异步回调代码语义不优雅、可读性较差。因此需要对原生 Storage 操作进行重封装,改为对内存中对象的实时存取,提高响应速度,并定期调用原生 API 向真实 Storage 中同步。

    实现原理

    getStorage と getStorageSync を基本 API として、同じ呼び出しメソッドで API をカプセル化します。初めて呼び出されるとき、ネイティブ API がトリガーされて元のデータを取得します。取得後、メモリ オブジェクトに保存されます。後続のすべての操作 (削除、変更、検索) はこのオブジェクトに基づいて行われます。操作を実行してください。設定操作と削除操作では、対応するデータをダーティとしてマークし、それをダーティ テーブルに保存して、後で変更をネイティブ エンドに同期できるようにする必要があります。呼び出し元は、メモリ実行中の偶発的なデータ損失を防ぐために、データを永続化する (同期されたダーティ テーブル内のデータを走査する) ために変更同期メソッドを定期的に呼び出す必要があります。一般に、定期的に実行する必要があります (アプリの onShow は setInterval を実行します)。アプリの onHide ライフサイクルで実行されます。

    Storage API を再カプセル化しただけでなく、時間のかかる他の同期 API (デバイスおよびシステム情報の取得に使用される getSystemInfo/getSystemInfoSync API など、基礎となる実装は同期です) も使用しました。同様に、システム API は最初の取得時にのみ呼び出され、結果がメモリにキャッシュされ、後続の呼び出しではキャッシュされた情報が直接返されます。

    4)、データ プリフェッチ

    1、パブリッシュおよびサブスクライブ メソッド

    実装アイデア

    からA ページがページ B にジャンプする前に、ページ A のエミット メッセージがページ B のデータ インターフェイス要求をトリガーし、結果データをキャッシュします。ページ B が開かれると、最初にキャッシュがフェッチされます。フェッチできない場合、インターフェイスは再度呼び出されました

    2eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

    実装原則

    #ページ B はインスタンス化されていませんが、ページは登録されており、ページの外部コードはが実行されているので、事前にページAでメッセージを完成させる パブリッシュとサブスクライブ

    2. グローバル登録変数メソッド

    実装アイデア

    プリロードする必要があるページがメイン パッケージに登録されていない場合、または非同期的に行われている場合、パブリッシュおよびサブスクライブ モードを介してプリリクエストを実行することはできません。プリロード メソッドをグローバルに登録することでこれを実現できます。

    実装原則

    前のページのルート ジャンプ プリリクエストを開始し、このリクエストをグローバル Promise 変数に保存し、プリロードする必要があるページがレンダリングされるときに、初回は、データ結果がグローバル Promise 変数に格納され、その後コールバックが最初に実行されます (

    5)、メモリ最適化

    1. 画像最適化

    画像リソース全体の最適化(Alibaba Cloud機能)

    • サイズ : 実際の幅と高さの1~2倍
    • Webp形式 : Android 側で完全に使用されます
    • Png 形式 : 要求の強いシーンのみ下部を透明にして使用、残りはデフォルトで Jpg/Jpeg を使用します
    • 画像遅延読み込み: 画像コンポーネントの遅延読み込み属性を有効にします
    2. ローエンド マシンのダウングレード

    実装アイデア

    ユーザー モデルのハードウェア パフォーマンス レベルに応じて、フロントエンド ディスプレイはさまざまなプレゼンテーション戦略を設定します

    ##実装原理#ローエンド マシン シナリオでは、次の機能をダウングレードします。

    gif アニメーションを静的画像にダウングレードします
    • JS および CSS アニメーションを静的スタイルにダウングレードします
    • 表示スワイパー コンポーネントなし
    • 品質は 60% を使用します
    • #3. ロングリストの最適化
    RecycleView
      IntersectionObserver
    • 2. ミニ プログラム エンジニアリング

    1) プラグイン フレームワーク

    フレームワーク ツール

    BeautyWe

    は 3 つです。パーティー向け小規模プログラム ライフスタイルの基礎となるパブリック ビジネス ロジックをカプセル化するビジネス開発フレームワーク

    アプリケーション シナリオ

    各ページでのユーザー ログイン ステータスの検証などのパブリック ビジネス ロジック。 URL パラメータの取得と処理、自動 PV 埋め込み、パフォーマンス監視など。

    実装原理

    ライフサイクル機能はプラグインであり、ネイティブの onLoad、onShow 、onReadyなどの関数をObject.definePropertyで書き換えて内部的にPromiseのタスクチェーンを形成するプラグインを導入することでタスクチェーンの前後にメソッドを自由に挿入できるシステムライフサイクル関数がトリガーされるタイミングが順番に実行され呼び出されます。

    ライフ サイクル フックのプラグインを実装した後、処理する必要があるすべてのタイプの基礎となるパブリック ロジックをカプセル化し、それをホスト (ネイティブ ライフ) に挿入できます。サイクル) Promise タスクチェーン2eコマースフロントエンドチーム向けの5年間の小規模プログラム開発経験のまとめ【役立つ情報満載】

    2)、自動デプロイメント

    ミニ プログラム CI Gitlab CI Puppeteer に基づいて、半自動ミニ プログラム構築およびデプロイメント ツールのセットが実装されています。他の記事「WeChat ミニ プログラム自動展開ソリューション」、WeChat ミニ プログラムは、Linux 環境で独立して実行できる miniprogram-ci を提供し、よりシンプルで使いやすくなります。

    3)、隠れたポイントの監視

    監視機能

    • ビジネスの隠れたポイント (ページ PV、モジュール露出などのビジネス フォーカス)

    • パフォーマンス レポート (ミニ プログラムの起動、ページ レンダリング、FMP、メモリ アラーム)

    • 例外監視 (JSエラー、インターフェースエラー、ビジネスエラー)

    パフォーマンス監視レポートタイプ

    • memory_warning: メモリ アラーム データのレポート。収集方法: wx.onMemoryWarning コールバックでアラーム レベルを収集

    • app_launch: アプリの実行時データのレポート。収集方法: アプリのライフサイクル実行時間 (onLaunch、onShow) を記録し、ページが onLoad のときにレポートします。

    • page_render: ページの実行時間データのレポート。収集方法:ページのライフサイクル実行時間(onLoad、onShow、onReady)、FMPなどを記録し、ページがonHideまたはonUnloadのときに報告します

    実装原理

    プラグイン フレームワークに基づいて、ページ プログラムの実行中にパフォーマンス データを自動的に記録およびレポートするようにライフ サイクル フック関数を書き換えます

    3. パフォーマンスの最適化実装と毎日のイテレーション仕様

    2 番目の開封率を測定するための重要な指標として FMP を使用します。詳細については、私の別の記事を参照してくださいユーザー エクスペリエンスを中心としたフロントエンド パフォーマンスの最適化。さらに、日々の開発において、日々のビジネス反復におけるパフォーマンスと安定性の基本保証を向上させることができるいくつかの仕様も作成しました。詳細については、WeChat ミニ プログラム開発軍事規則 を参照してください。

    4. 概要の考え方と開発の見通し

    インフラストラクチャ機能の継続的な改善

    公式ドキュメントは、フレームワークの基礎となる技術 この開示は、ミニプログラムの技術構築がますます成熟し、完璧になりつつあることを示しています。インフラストラクチャ エコシステムの継続的な強化に伴い、当局は同層レンダリング、ネットワーク環境モニタリング、初期レンダリング キャッシュ、起動パフォーマンスの最適化などのこれらの機能のサポートを継続的に提供し、ミニ プログラムを徐々に Web エコシステムに近づけてきました。

    私たち自身のビジネスの反復において、さまざまな問題を解決するために、下請けと非同期化、CI パッケージ化、パフォーマンス API などの多くの車輪を自分たちで作成してきました。WeChat は後にこれらの機能をネイティブに実装します。無駄な努力のように思えるかもしれませんが、実際にはこれまで私たちがやってきたことは正しく、その方向性はエコシステム全体の発展と一致していることを示しているだけです。

    ビジネスを強化するさらなるシナリオ

    技術的な能力の向上に加えて、WeChat ミニ プログラム エコシステムは、次のようなより多くのビジネス シナリオにおける能力サポートも常に充実させています。モーメントの共有、短いリンクの生成、ミニ プログラムを開くための WeChat チャット資料のためのミニ プログラムをサポートし、当社のビジネスにさらなる可能性と想像力を提供します。

    WeChat は、ミニ プログラム ハードウェア フレームワークも開始しました。これにより、ハードウェア デバイス (非汎用コンピューティング デバイス) が、WeChat クライアントを実行するための条件を満たしていない場合でも、WeChat ミニ プログラムを実行できるようになります。Android で使用できます。大画面デバイスなどのハードウェアは、低コストの画面インタラクション ソリューションを提供し、IoT デバイス ユーザーに、より標準化された機能豊富なエクスペリエンスを提供します。

    これは、コンピュータ テクノロジの分野で数十年にわたって広まってきた格言 アトウッドの法則を思い出させます。JavaScript で記述できるアプリケーションは、最終的には JavaScript で記述されることになります。同様に、ミニ プログラムを使用して実装できる製品は、最終的にはミニ プログラムを使用して実装されます。

    小程式發展前景展望

    自從2017 年微信小程式誕生以來,超級App 小程式/輕應用程式的這種模式在各種業務中屢試不爽,例如微信和微信小程式、支付寶和支付寶小程式、抖音和抖音小程式等等,小程式這種成本低、迭代快、易推廣的產品模式,在超級App 帶來的巨大流量加持下,在各個領域都獲得了巨大的成功,並且已經逐漸成為一種趨勢,越來越多的公司在自己的產品中加入了這種模式。小程式本身也已經在不知不覺中融入了生活點滴中,疫情期間各個地區的健康碼應用,小區裡的電商團購、飯店點餐的小程序碼,想喝奶茶咖啡在小程序上提前下單,人們的生活已經與小程式緊不可分,小程式這項產品技術方案確實實創造了極大的社會價值。

    我曾經與朋友聊天時戲稱小程式是具有中國特色的PWA 應用,面向未來小程式仍然大有可為,除了現有佔比較高的網路購物和生活服務類應用,在更多的場景下也都能看到小程式技術的用武之地,例如在健康醫療、線下零售、娛樂遊戲、AI 智慧等產業領域內遠遠沒有達到飽和的狀態,市場空白讓小程式的開發潛力變得更大,小程式正向當初設立的目標讓小程式觸手可及,無處不在 不斷邁進。

    原文網址:https://juejin.cn/post/7100752247381819399

    (學習影片分享:web前端入門

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