マイクロフロントエンドアーキテクチャは、 フロントエンド アプリは、個別の半独立した「マイクロアプリ」に分解され、大まかに連携します。マイクロフロントエンドの概念は、マイクロサービスに漠然と着想を得ており、マイクロサービスにちなんで名付けられています。
マイクロフロントエンドパターンの利点は次のとおりです。
マイクロフロントエンドは最近多くの注目を集めていますが、現時点では、単一の主要な実装や明確な「最良の」マイクロフロントエンドフレームワークはありません。実際、目的や要件に応じてさまざまなアプローチがあります。よく知られている実装のいくつかについては、参考文献を参照してください。
この記事では、マイクロフロントエンドの理論の多くをスキップします。これが私たちの しません カバー:
代わりに、具体的な実装に焦点を当てたマイクロフロントエンドチュートリアルを紹介し、マイクロフロントエンドアーキテクチャの重要な問題とその可能な解決策に焦点を当てます。
私たちの実装はYumchaと呼ばれます。広東語で「飲茶」の文字通りの意味は「お茶を飲む」ですが、日常の意味は「点心に出かける」です。ここでの考え方は、内の個々のマイクロアプリは macroapp (構成されたトップレベルのアプリと呼びます)は、点心ランチで持ち出される一口サイズのさまざまなバスケットに似ています。
Yumchaを「マイクロフロントエンドフレームワーク」と呼ぶこともあります。今日の世界では、「フレームワーク」という用語は通常、Angular、React、Vue.js、またはその他のWebアプリの同様の上部構造を指すために使用されます。私たちは話していません その意味でのフレームワーク まったく。 Yumchaは、便宜上、フレームワークと呼んでいます。実際には、マイクロフロントエンドベースのアプリを構築するための一連のツールといくつかの薄いレイヤーです。
マクロアプリとそれを構成するマイクロアプリをどのように定義するかを考えてみましょう。マークアップは常にWebの中心にあります。したがって、macroappは、このマークアップよりも複雑なものによって指定されます。
マークアップを使用してマクロアプリを定義すると、マイクロアプリをレイアウトおよび管理するためのHTMLとCSSの機能に完全にアクセスできます。たとえば、あるマイクロアプリを別のマイクロアプリの上または横に置いたり、ページの隅に置いたり、アコーディオンの1つのペインに置いたり、何かが起こるまで非表示のままにしたり、バックグラウンドに永続的にとどまったりすることができます。 。
「ポータル」はマイクロアプリで使用されるマイクロアプリの有望な用語であるため、マイクロアプリに使用されるカスタム要素に名前を付けました。 ポータル提案 、マイクロフロントエンドで使用するための標準HTML要素を定義する初期の試み。
どのように実装する必要がありますか?もちろん、これはWebコンポーネントとしてのカスタム要素なので、!マイクロフロントエンドWebコンポーネントの作成とコンパイルについては、多数の強力な候補の中から選択できます。ここで使用します LitElement 、PolymerProjectの最新のイテレーション。 LitElementは、TypeScriptベースのシンタックスシュガーをサポートしています。これは、カスタム要素のボイラープレートのほとんどを処理します。私たちのページで利用できるようにするには、上記のように、関連するコードをとして含める必要があります。
しかし、実際には何をしますか?最初の概算は、iframe
を作成することです。指定されたソースで:
render() { return html` `; }
…ここでrender
html
を使用する標準のLitElementレンダリングフックです。タグ付きテンプレートリテラル。この最小限の機能は、いくつかの些細なユースケースにはほぼ十分かもしれません。
iframe
にマイクロアプリを埋め込むiframe
sは誰もが嫌うHTML要素ですが、実際には非常に便利で堅実なサンドボックス動作を提供します。ただし、iframe
を使用する際に注意すべき問題のリストはまだたくさんあり、アプリの動作と機能に影響を与える可能性があります。
動作するリークされたクレジットカード
iframe
には、サイズとレイアウトの点でよく知られている癖があります。iframe
に。iframe
の現在のナビゲーションステータスページのURLには反映されません 、そのため、作成されたアプリの同じ状態に到達するためにURLを切り取って貼り付けることも、それらへのディープリンクもできませんでした。iframe
とのコミュニケーションCORSの設定に応じて、外部から postMessage
を通過する必要があるかもしれませんプロトコル 。iframe
全体の認証境界 。iframe
で境界またはiframe
が必要ユーザーにアナウンスできるタイトルを付ける。これらの問題のいくつかは、iframe
sを使用しないことで回避または軽減できます。これは、この記事の後半で説明する代替手段です。
プラス面では、iframe
独自の独立した Content-Security-Policy
(CSP)。また、iframe
というマイクロアプリの場合Service Workerを使用するか、サーバー側のレンダリングを実装することを指している場合、すべてが期待どおりに機能します。 iframe
にさまざまなサンドボックスオプションを指定することもできますトップフレームに移動できるなど、その機能を制限します。
一部のブラウザは、loading=lazy
を出荷しているか、出荷を計画しています。 iframe
sの属性。これは、スクロールせずに見える範囲のiframe
sの読み込みを、ユーザーがスクロールするまで延期しますが、これでは、必要な遅延読み込みをきめ細かく制御できません。
iframe
sの本当の問題は、iframe
の内容です。取得するには複数のネットワークリクエストが必要です。トップレベルindex.html
が受信され、スクリプトが読み込まれ、HTMLが解析されます。ただし、ブラウザはiframe
のHTMLに対する別のリクエストを開始し、受信を待ち、スクリプトを解析して読み込み、| _ +をレンダリングする必要があります。 _ |の内容。多くの場合、iframe
のJavaScriptは、スピンアップして独自のAPI呼び出しを行い、それらのAPI呼び出しが返され、データが表示用に処理された後にのみ、意味のあるデータを表示する必要があります。
これにより、特に複数のマイクロアプリが関係している場合に、望ましくない遅延やレンダリングアーティファクトが発生する可能性があります。 iframe
のアプリがSSRを実装している場合、それは役に立ちますが、それでも追加の往復の必要性を回避することはできません。
したがって、ポータル実装を設計する際に直面する重要な課題の1つは、このラウンドトリップの問題にどのように対処するかです。私たちの目標は、単一のネットワークリクエストで、各マイクロアプリが事前入力できるコンテンツを含め、すべてのマイクロアプリを含むページ全体を停止することです。この問題の解決策は、Yumchaサーバーにあります。
ここで紹介するマイクロフロントエンドソリューションの重要な要素は、マイクロアプリの構成を処理するための専用サーバーをセットアップすることです。このサーバーは、各マイクロアプリがホストされているサーバーにリクエストをプロキシします。確かに、このサーバーをセットアップして管理するには、ある程度の努力が必要です。一部のマイクロフロントエンドアプローチ(例: シングルスパ )展開と構成の容易さという名目で、このような特別なサーバー設定の必要性をなくそうとします。
ただし、このリバースプロキシを設定するコストは、私たちが得るメリットによって十分に相殺されます。実際、マイクロフロントエンドベースのアプリには、それなしでは実現できない重要な動作があります。このようなリバースプロキシを設定するための多くの商用および無料の代替手段があります。
リバースプロキシは、マイクロアプリリクエストを適切なサーバーにルーティングするだけでなく、ルーティングも行います macroapp macroappサーバーへのリクエスト。そのサーバーは、作成されたアプリのHTMLを特別な方法で処理します。 iframe
のリクエストを受け取ったときブラウザからindex.html
などのURLのプロキシサーバーを経由して、http://macroapp.example.com
を取得します。次に、それを返す前に、単純ですが重要な変換を行います。
具体的には、HTMLは解析されたfortagであり、Node.jsエコシステムで利用可能な有能なHTMLパーサーの1つを使用して簡単に実行できます。 index.html
を使用する属性に、microappを実行しているサーバーに接続し、そのsrc
サーバー側でレンダリングされたコンテンツがあればそれも含めて取得されます。結果は、ブラウザによって実行されないように、aortagとしてHTML応答に挿入されます。
この設定の利点には、何よりもまず、index.html
の最初の要求での利点が含まれます。作成されたページの場合、サーバーは、SSRでレンダリングされたコンテンツ(存在する場合)を含め、個々のmicroappサーバーから個々のページを完全に取得し、データの入力に使用できるコンテンツを含む単一の完全なページをブラウザーに配信できます。 index.html
追加のサーバーラウンドトリップなし(十分に活用されていないiframe
属性を使用)。プロキシサーバーはまた、マイクロアプリが提供されている場所の詳細が詮索好きな目から隠されていることを確認します。最後に、アプリケーション要求はすべて同じオリジンに対して行われるため、CORSの問題が単純化されます。
クライアントに戻ると、タグはインスタンス化され、サーバーによって応答ドキュメントに配置されたコンテンツを見つけ、適切なタイミングでsrcdoc
をレンダリングします。コンテンツをiframe
に割り当てます属性。 srcdoc
sを使用していない場合(以下を参照)、そのタグに対応するコンテンツは、カスタム要素のシャドウDOMを使用している場合はそのDOMに挿入されるか、ドキュメントに直接インラインで挿入されます。
春のセキュリティトークンベースの認証例
この時点で、すでに部分的に機能しているマイクロフロントエンドベースのアプリがあります。
これは、Yumchaサーバーの興味深い機能という点で氷山の一角にすぎません。たとえば、マイクロアプリサーバーからのHTTPエラー応答の処理方法や、応答が非常に遅いマイクロアプリの処理方法を制御する機能を追加する必要があります。1つのマイクロアプリが処理されない場合、ページを提供するために永遠に待つ必要はありません。応答します!これらおよびその他のトピックは、別の投稿に残します。
Yumchaマクロアプリiframe
変換ロジックは、サーバーレスラムダ関数方式で、またはExpressやKoaなどのサーバーフレームワークのミドルウェアとして簡単に実装できます。
クライアント側に戻ると、効率、遅延読み込み、ジャンクのないレンダリングに重要なマイクロアプリの実装方法には別の側面があります。私達 たぶん......だろう index.html
を生成します各マイクロアプリのタグ(iframe
)属性(別のネットワーク要求を行う)またはsrc
を使用サーバーによって入力されたコンテンツが入力された属性。しかし、どちらの場合も、その中のコードはsrcdoc
ユーザーが問題のマイクロアプリにアクセスしたことがない場合でも、すべてのスクリプトとリンクタグの読み込み、ブートストラップ、初期API呼び出しと関連データ処理を含め、すぐに開始されます。
この問題に対する私たちの解決策は、最初にページ上のマイクロアプリを小さな非アクティブ化されたスタブとして表し、その後アクティブ化することです。アクティベーションは、十分に活用されていないiframe
を使用して、表示されるマイクロアプリの領域によって駆動できます。 API、またはより一般的には外部から送信される事前通知によって。もちろん、microappをすぐにアクティブにするように指定することもできます。
いずれにせよ、マイクロアプリがアクティブ化されたときのみ、IntersectionObserver
です。実際にレンダリングされ、そのコードがロードされて実行されます。 LitElementを使用した実装に関して、アクティベーションステータスがiframe
で表されると仮定します。インスタンス変数の場合、次のようになります。
activated
マクロアプリを構成するマイクロアプリは、定義上疎結合ですが、それでも相互に通信できる必要があります。たとえば、ナビゲーションマイクロアプリは、ユーザーが選択した他のマイクロアプリをアクティブ化する必要があるという通知を送信する必要があり、アクティブ化するアプリはそのような通知を受信する必要があります。
私たちのミニマリストの考え方に沿って、私たちは多くのメッセージパッシング機構を導入することを避けたいと思っています。代わりに、Webコンポーネントの精神で、DOMイベントを使用します。差し迫ったイベントのすべてのスタブに事前通知し、そのイベントタイプがアクティブ化されるまでアクティブ化を要求したものを待機し、マイクロアプリがリッスンできるドキュメントに対してイベントをディスパッチする簡単なブロードキャストAPIを提供しますそれ。すべてのrender() { if (!this.activated) return html`{this.placeholder}`; else return html` `; }
が同一生成元であるとすると、iframe
から連絡できます。ページに移動し、その逆を行って、イベントを発生させる要素を見つけます。
今日、私たちは皆、SPAのURLバーがアプリケーションの表示状態を表すことを期待するようになりました。そのため、切り取り、貼り付け、メール、テキスト、およびそれにリンクして、アプリ内のページに直接ジャンプできます。ただし、マイクロフロントエンドアプリでは、アプリケーションの状態は実際には状態の組み合わせであり、各マイクロアプリに1つずつあります。これをどのように表現し、制御するのですか?
解決策は、各マイクロアプリの状態を単一の複合URLにエンコードし、その複合URLをまとめて分離する方法を知っている小さなマクロアプリルーターを使用することです。残念ながら、これには各microappにYumcha固有のロジックが必要です。macroappルーターからメッセージを受信してmicroappの状態を更新し、逆に、複合URLを更新できるようにmacroappルーターにその状態の変化を通知します。たとえば、iframe
を想像できます。 Angularの場合、またはReactの要素。
YumchaLocationStrategy
場合上記のように、iframe
sでマイクロアプリをホストすることにはいくつかの欠点があります。 2つの選択肢があります。ページのHTMLに直接インラインで含めるか、ShadowDOMに配置します。どちらの方法も、iframe
sの長所と短所をある程度反映していますが、方法が異なる場合もあります。
たとえば、個々のmicroappCSPポリシーを何らかの方法でマージする必要があります。スクリーンリーダーなどの支援技術は、シャドウDOMをサポートしていると仮定すると、iframe
sよりもうまく機能するはずです(まだすべてがサポートされているわけではありません)。 「スコープ」のサービスワーカーの概念を使用してマイクロアプリのサービスワーカーを登録するように手配するのは簡単ですが、アプリはサービスワーカーがiframe
ではなくアプリの名前で登録されていることを確認する必要があります。 '/'
に関連するレイアウトの問題はありませんインラインまたはシャドウDOMメソッドに適用します。
ただし、AngularやReactなどのフレームワークを使用して構築されたアプリケーションは、インラインまたはシャドウDOMでの生活に不満を抱く可能性があります。それらの場合、iframe
sを使用する可能性があります。
CSSに関しては、インラインDOMメソッドとシャドウDOMメソッドが異なります。 CSSはShadowDOMにきれいにカプセル化されます。何らかの理由でCSSの外部をシャドウDOMと共有したい場合は、 構築可能なスタイルシート または同様のもの。インライン化されたマイクロアプリを使用すると、すべてのCSSがページ全体で共有されます。
結局、インラインおよびシャドウDOMマイクロアプリのロジックの実装は簡単です。特定のマイクロアプリのコンテンツを、サーバーロジックによってHTML要素としてページに挿入された場所から取得し、クローンを作成してから、LitElementが呼び出すiframe
に追加します。これは通常、要素のシャドウDOMですが、インライン(非シャドウDOM)の場合は、要素自体(renderRoot
)にも設定されます。
ちょっと待って! microappサーバーによって提供されるコンテンツは、HTMLページ全体です。 this
、html
、およびhead
を含むmicroappのHTMLページを挿入できません。タグ、macroappのタグの真ん中に、できますか?
body
の癖を利用して、この問題を解決します。 microappサーバーから取得したmicroappコンテンツがラップされているタグ。最近のブラウザがtemplate
に遭遇するとタグ、彼らはそれを「実行」しませんが、彼らはします 解析する そうすることで、内部コンテンツを保持しながら、、、およびタグなどの無効なコンテンツを削除します。そのため、のコンテンツだけでなく、のandtagsも保持されます。これはまさに、マイクロアプリのコンテンツをページに挿入するために必要なものです。
マイクロフロントエンドは、(a)より優れたアーキテクチャアプローチであることが判明し、(b)今日のウェブの無数の実用的な要件を満たす方法でマイクロフロントエンドを実装する方法を理解できれば、webappエコシステムに定着します。
最初の質問に関しては、マイクロフロントエンドがすべてのユースケースに適したアーキテクチャであるとは誰も主張していません。特に、単一のチームによるグリーンフィールド開発がマイクロフロントエンドを採用する理由はほとんどありません。マイクロフロントエンドパターンから他のコメンテーターに最も恩恵を受ける可能性があるのは、どのタイプのコンテキストのどのタイプのアプリかという質問を残しておきます。
実装と実現可能性の観点から、この記事で言及されていないもの、特に認証とセキュリティ、コードの複製、SEOなど、関係するさまざまな詳細があります。それでも、この記事で、マイクロフロントエンドの基本的な実装アプローチを説明し、さらに改良を加えることで、実際の要件に対応できることを願っています。
マイクロフロントエンドは、WebアプリケーションUI(フロントエンド)が、さまざまなテクノロジを使用してさまざまなチームが構築できる半独立したフラグメントから構成される新しいパターンです。マイクロフロントエンドアーキテクチャは、バックエンドが半独立したマイクロサービスで構成されているバックエンドアーキテクチャに似ています。
マイクロフロントエンドアーキテクチャは、マイクロフロントエンドフレームワークの構造要素に対するアプローチを示しています。また、それらの間の関係を定義し、最適な開発者とユーザーエクスペリエンスを実現するために、UIフラグメントがどのように組み立てられて通信するかを管理します。
はい、ある意味で可能です。マイクロフロントエンドパターンは、UIを提供するために、おそらくマイクロフロントエンドWebコンポーネントとして実装されているマイクロフロントエンドの1つのフラグメントをマイクロサービスとペアにするアプローチを採用することがよくあります。
マイクロサービスは、アプリケーションが相互運用サービスのコレクションとして構造化されているアーキテクチャの要素です。フロントエンドがマイクロフロントエンドパターンを採用している場合、マイクロサービスはマイクロフロントエンドとペアになる可能性があります。
マイクロフロントエンドとWebコンポーネント(カスタム要素)は、いくつかの方法で関連付けることができます。 Webコンポーネントは、マイクロフロントエンドアプリケーションを構成するマイクロアプリを記述するための自然なマークアップベースの方法です。また、マイクロフロントエンドアプリケーションの個々のマイクロアプリ自体は、Webコンポーネントを使用して構築できます。