メインコンテンツへ移動

もし Web が当初動的化をサポートしていなかったら

無料2020-10-03#Mind#移动端动态化#客户端容器化#移动端动态更新#热修复#插件化

もし Web が当初動的化をサポートしていなかったら、フロントエンド大軍はどのような動的化の道を切り開いたでしょうか?

楔子

Web は生まれつき極めて柔軟な動的化基礎能力を備えています。例えば:

  • 動的にscript タグを挿入して任意のスクリプトロジックを実行

  • 動的にstyle タグを挿入して任意の CSS スタイルルールを導入

  • iframe タグを通じてサイト全体を埋め込み

  • 上記のタグはすべて直接ネットワークリソースをロード可能

  • これらのコンテンツを承载する Web ページはリモートサーバーにデプロイされ、いつでも動的更新可能で、かつ即座に生效

これまでの探索と実践は、絶えず動的化能力のエンジニアリング価値を発掘し、より適切な応用シナリオを探しているに過ぎません。例えば初期のframeset、現在の 微前端/微応用 など

一方、モバイルエンドはちょうど逆で、生まれつき多くの柔軟性制限を備えています:

  • ネイティブは動的にロジックコードを実行することをサポートしない

  • モバイルアプリケーションを構成する重要なリソースの大部分はインストールパッケージに打ち込む必要がある([動的ライブラリ](/articles/node-js-c 拡張入門ガイド/) は例外)

  • アプリケーションはユーザーデバイスにインストールされ、インストールパッケージの更新はアプリストアの審査を経る必要があり、ユーザーが再インストールして初めて生效

モバイル業務の発展は絶えず動的化能力により高い要求を提起していますが、動的化の基礎能力が不足しているため、常にさらに柔軟な技術方案を探索しています。例えば初期のホットフィックス/ホットアップデート、現在のミニプログラムなど

実際、二者は動的化技術能力上で解決すべきエンジニアリング問題は一致しています。例えば動的に依存ライブラリ、ビューコンポーネント、さらにはアプリケーション全体をロードするなど。したがって、Web が動的化をサポートしていないと仮定し、Native の業務訴求に基づいて Web 動的化技術の発展軌跡を推演してみましょう

伊始:ネイティブ WebAssembly

0061 736d 0100 0000 0187 8080 8000 0160
027f 7f01 7f03 8280 8080 0001 0004 8480
8080 0001 7000 0005 8380 8080 0001 0001
0681 8080 8080 000007 9080 8080 0002 066d
656d 6f72 7902 0003 6763 6400 000a ab80
8080 0001 a580 8080 0001 017f 0240 2000
450d 0003 4020 0120 0022 026f 2100 2002
2101 2000 0d00 0b20 020f 0b20 010b

昔、Web アプリケーションはこの[wasm](/articles/webassembly 試玩/) のようなバイナリ形式にパッケージ化され、各大手ブラウザアプリストアにリリースされるしかありませんでした。その間、数日間の審査を待つ必要があり、通過した後もユーザーが積極的に更新をインストールするのを待つ必要があり、新版本が本当に「生效」する(大多数のユーザーをカバーする)までには、すでに数ヶ月後になっている可能性がありました

バージョン更新が遅く、戦略的に重要な機能でも十万火急の問題修復でも、タイムリーにユーザーに届けることができません。たとえオンラインで火事が発生しても、最も迅速な消火方案でも数日甚至数週間後でなければ効果を発揮できません

より迅速に問題を修復し、リスクを低減するために、ホットフィックス方案の探索がここに始まりました

浪花:ホットフィックスのためにスクリプト言語 JavaScript を導入

ホットフィックスは(インストールパッケージ外の)ロジックコードをロードして実行する必要があるため、有人は直接 WebAssembly モジュールロードメカニズムから着手し、いくつかの Hook 方案を研究し出し、動的に某些モジュール/ファイルを入れ替えることができました

有人はこの方向にさらに遠くまで進み、时效性、性能、互換性と安定性を权衡し、コンパイル挿桩、エンジニアリング付帯施設、ランタイムフレームワークなどの手段を通じてモジュール依存、バージョン管理、差量更新などの問題を解決し、アプリケーションの各機能モジュールをプラグイン化しました

有人は別の道を開き、軽量級のスクリプト言語ランタイム(JavaScript エンジンなど)を導入し、ブラウザネイティブ WebAssembly と JavaScript 世界の間に橋を架け、JavaScript を通じてネイティブのシステムプラットフォーム能力を呼び出すことを許可し、これにより動的化の基礎能力を拡張しました

動的化は一道の波紋を漾起し、続いて呼啸而来的な動的更新の浪潮が来ました

海嘯:JavaScript に基づく動的更新

動的化の方向に一歩を踏み出した後、全面的な動的化の素晴らしい前景まであと一歩となりました:

Any application that can be written in JavaScript, will eventually be written in JavaScript. —— Jeff Atwood

The Principle of Least Power より抜粋)

全面的な動的化は以下を意味します:

  • アプリケーション中で動的化可能なすべての部分を JavaScript で実装するように移行

  • 膨大な JavaScript コードを機能モジュールごとに組織し、機能モジュール間の依存関係を管理

これにより機能モジュールを単位とした迅速なイテレーションを実現し、ホットフィックス技術を問題修復以外のニーズイテレーションに適用することに相当し、バージョンを発行する必要がなく、審査サイクルを免去し、ユーザーが積極的にインストールするのを待つ必要もなく、新機能が動的にリリースされ、迅速にアクティブユーザーをカバー

堤壩:コンテナ概念の形成

動的化程度の不断の向上に伴い、JavaScript のアプリケーション中の占比はますます高くなり、最終的に動的化できない(または動的化する必要がない)部分のみが WebAssembly で実装されるようになりました。以下を含みます:

  • システムプラットフォーム能力ブリッジ

  • 基礎 UI コントロール、インタラクション能力

  • ビュー層フレームワーク(履歴スタック管理、ライフサイクルサポートなど)

  • 特定の業務領域能力(例えばマルチメディアコンテンツ制作、IM SDK など)

  • 通信メカニズム(ブロードキャスト、状態共有など)

これらの部分はコンテナ(ネイティブ外殻)を形成し、ブラウザ中で実行される動的化ランタイムに相当し、コンテナが圏定した能力範囲内で、業務は動的優勢を十分に利用し、迅速な修復、迅速なリリース、迅速な到達、迅速なイテレーションを実現できます

しかしコンテナ概念と共に現れたのは、業務をより速く走らせる赋能之外に、動的業務とコンテナ間の依存問題もあります:

  • 二者間の強結合をどのように解除するか、例えばルート、混合ビューコンテナなどのシナリオ?

  • 二者間の依存関係をどのように識別するか?

  • 依存関係が制御可能であることをどのように保証するか、例えば新能力に依存する動的業務を旧コンテナにリリースすることを禁止?

エンジニアリング付帯施設を通じて依存を管束した後、次の首要問題は動的業務が依存する底層コンテナの信頼性を保証する方法を考えることです

境界:HTML、JavaScript、CSS がコンテナ標準を構成

変化を隔離する慣用手段は抽象層を 1 層追加し、変化する部分を抽象層の下に置くことです:

  • BOM API:システムプラットフォーム、ビュー層フレームワーク能力および通信メカニズムの抽象

  • Native Module API:特定の業務領域能力の抽象

  • DOM API:基礎ビューレンダリング能力の抽象

  • JS API:JavaScript ランタイムの抽象

  • CSS:スタイル、レイアウト能力の抽象

  • HTML:基礎 UI コントロール、インタラクション能力の抽象

抽象化されたこれらの標準は稳固なコンテナ境界を確立し、境界の内側では、動的業務は肆意に発揮でき、境界の下では、コンテナも不断に精進し、コンテナ能力を豊富にし、境界を拓宽できます。同時に、標準定義された API は構造化された形式で維持でき、開発体験に大いに裨益します

雲海:ブラウザがネットワークリソースのロードをサポート

另一方面、標準化の過程で、いくつかの動的化業務実践もコンテナの中に沈殿しました。例えば:

  • 動的スクリプト:script がネットワークリソースのロードをサポート

  • 動的スタイル:style がネットワークリソースのロードをサポート

  • 動的ルート:ブラウザが直接 URL を通じてロード、またはiframe を通じてネットワークアプリケーションを埋め込むことをサポート

ホットフィックスから CDN から JS ファイルを_PULL し、ランタイムで動的に解釈実行できましたが、コンテナ標準はこの方式に便捷的なサポートを提供するだけでなく、動的化の基礎能力をロジックからビュー、スタイル、静的リソースなどに拡大しました

至此、動的化で最も重要な基礎能力が完備しました。JavaScript に移行した機能モジュールはさらにクラウドにデプロイでき、オフライン統合、オンライン托管の 2 つのモードの柔軟な切り替えを実現

一色:同期、非同期モードの切り替え自在

完備した動的化基礎能力は多くの新しい玩法をロック解除しました。例えば:

業務モジュール(bundle)をさらに機能モジュール(chunk)に分割し、非コアモジュールを非同期し、動的按需ロードを実現します。例えばサードパーティ JS SDK、jQuery プラグイン、およびシェア/コメント/都市選択などの重量級コンポーネント

コンテンツ提示の偏静的シナリオに対しては、SSR を通じてサーバーサイドで(大部分の)ページレンダリング作業を完了し、初画面コンテンツ提示を加速できます

另一方面、Hydration、lazy コンポーネント、Suspense などのランタイム特性により、オンラインの動的部分とオフラインの非動的部分を十分に融合でき、より細粒度の業務動的化を実現し、オンライン托管を真に 1 つのデプロイオプションにします

与此同时、動的業務自身のコンポーネント化程度も不断に深まり、フロントエンド開発の核心作業はページ、モジュール開発からコンポーネント、編成ロジック開発に移行しました

流雲:データ駆動のフロントエンドアプリケーション

コンポーネント体系が趋向成熟した後、由来已久的な概念がついに完全に浮上しました——データ駆動

前後端分层のデータプロトコルから、徐々にデータ駆動に進化しました。ここのデータは 3 部分を含みます:

  • 後端業務領域データ

  • フロントエンド状態データ

  • (後端業務領域データに基づく)フロントエンド派生データ

これらのデータを業務コンポーネントに填入すれば、完全な機能モジュールをレンダリングできます(クライアントでもサーバーサイドでも)、それをビューコンテナ中の適切な坑位に放置すれば、1 回のコンポーネント級の「リリース」過程が完了します

このモードは 5 つの重要な環節を含みます:

  • 業務データ(後端業務領域データとフロントエンド派生データを含む)の生産

  • 業務コンポーネント(フロントエンド状態データを含む)の生産と維持

  • コンポーネントのレンダリング(業務データ + 業務コンポーネント = 機能モジュール

  • 坑位の生産

  • 機能モジュールの投放

その中で、業務コンポーネント、坑位はさらに動的化の鍵であり、4 つの段階に分けられます:

  • 一個蘿蔔一個坑:静的業務コンポーネント + 静的坑位

  • 一個蘿蔔到處扔:静的業務コンポーネント + 動的坑位

  • 多個蘿蔔番輪扔:動的業務コンポーネント + 静的坑位

  • 多個蘿蔔到處扔:動的業務コンポーネント + 動的坑位

多個蘿蔔到處扔のコンポーネント級動的化究極目標に到達するには、業務コンポーネントを動的リリース、坑位を動的リリースできる必要があります

交融:動的業務コンポーネント + 動的坑位

端と雲の視点から見ると、業務コンポーネントもデータ(雲)の一部と見なせます。相比之下坑位と端の关联はより緊密で、動的化の唯一の手段は端側のものを雲上に移すことなので、解決すべき鍵問題はどのように坑位の動的化を実現するかです

2 つの思路があります:

  • 坑位の概念を干掉:坑位の概念をコンポーネント級からページ級に拡張し、1 つのページコンテナ(1 つの URL)即ち 1 つの坑位

  • 坑位をコンポーネント化:標準的な坑位コンポーネントを提供し、iframe のように

ページは天然的な動的坑位で、新しいページコンテナを開いて任意の URL をロードできます

ページ以外の其它レイアウトコンテナに対して、例えば対話框、メッセージ条、Banner 位、腰封などは、坑位を標準化してコンテナコンポーネントにし、業務コンポーネントと共に動的リリースし、坑位の賃貸関係をサービス端で維持し、データ駆動のデータの一つとします

至此、前後端分层の境界は何度も再定義され、ついに JSP/PHP がデータとテンプレートを融合した黄金年代を迎えました……

参考資料

コメント

コメントはまだありません

コメントを書く