マイクロフロントエンドについて調査したのでまとめてみた[詳細編]
みなさんこんにちは!
ワンキャリアの西川(X (旧twitter):takashi54461358)です!
前回の記事「マイクロフロントエンドについて調査したのでまとめてみた[概念編]」では、ざっくりとマイクロフロントエンドとはどういうものか、メリット・デメリットについて記載しました。
今回の記事ではマイクロフロントエンドの実装について深堀りしていきます。最初に体系的にマイクロフロントエンドの実現方法を説明したあと、各分割パターン・組成パターンについて説明していきます。
復習
マイクロフロントエンドとは、複雑で巨大に感じる一つのプロダクトを小さいシステム(独立して開発、テスト、デプロイできる)を組み合わせることで成り立たせるためのアーキテクチャです。
具体的には以下のようにいくつかのフラグメント(あるいはアプリケーション)を一つのサービスとしてまとめたものをマイクロフロントエンドと呼びます。(以降、分割した物をフラグメントと呼びます)
前回の記事で、マイクロフロントエンドを実現するためには「どのように一つのサービスを分けるか」と「どのように分割したものを組み立てるか」の2つを考える必要があると述べました。自分が調査する際によく参考にしたこちらの記事では、1つのサービスをどのように分けるかを「分割パターン」、どのように分割したものを組み立てるかを「組成パターン」と呼んでいます(本記事ではこの呼び方を用いて説明します)。
分割パターンと組成パターンの組み合わせ
組成パターンと分割パターンを整理すると下記の画像のようになります。
まず、水平分割と垂直分割のどちらを選択するかを決定し、水平分割の場合はどの組成方法を採用するか、そしてどの技術を使用するかを決定します。それぞれのパターンにはメリットとデメリットが存在し、適しているサービスが異なるため慎重な検討が必要です。
分割パターンの詳細
前回の記事でも紹介しましたが、分割パターンは「水平分割」「垂直分割」の二つのパターンが存在します。大雑把に言うと、一つのプロダクトをコンポーネント単位またはページ単位のどちらで分割して管理したいかによって選択が変わります。
水平分割
水平分割では一つのプロダクトをコンポーネント単位で分割・管理します。具体的には、チームがサブドメインごとの開発に集中できるよう依存・関心を分離するために、機能をUI含めてコンポーネントとして切り分けて管理します。こうすることで、各サブドメインの開発・強化をチーム単位で独立して進めることができます(マイクロフロントエンドの大きなメリットです)。下記の画像ではECサイトを例として、「検索」「商品表示」「おすすめ」の3つの機能にプロダクトを分解する例を示しています。
垂直分割
垂直分割では、一つのプロダクトをページ単位で分割・管理します。こちらも水平分割と同様に、チームがサブドメインごとの開発に集中できるよう依存・関心を分離することが目的です。水平分割と異なるのは、サブドメインがページごとにまとまっているため、分割単位もまたページ単位になるという点です。
忘れてはならないのは、あくまで分割の目的が「各サブドメインの開発・強化をチーム単位で独立して進めること」であるという点です。機能同士の関心ごとが重複しているにも関わらず、機能に着目して分割を進めてしまうと、せっかくチームに分けて開発しても、重複している関心ごとについてのミーティングや衝突が多く発生して開発がより遅くなってしまうということになりかねません。
組成パターンの詳細
分割したフロントエンドを一つのアプリケーションとして統合して提供する方法は、こちらの記事で「クライアントサイド組成パターン」「サーバーサイド組成パターン」「エッジサイド組成パターン」の大きく3つのパターンに分けて説明されています。
クライアントサイド組成パターン
クライアントサイド組成パターン(クライアントサイドコンポジションとも呼ばれる)はコンテナアプリケーション(アプリケーションシェルとも呼ばれ、ユーザーがアクセスした際に一番最初に呼び出される統合用アプリケーション)がブラウザ内でレンダリング処理をする際にフラグメント(分割されているアプリケーション)を統合する方法です。
この方法はさらに大きく次の2つのパターンに分けることができます。
iframeを利用した方法
Web Componentsなどでコンポーネントを関数から呼び出す方法
iframeを利用した方法では、フラグメントとなるアプリケーションをiframeを通して呼び出すことで、コンテナアプリケーションからフラグメントをコンポーネントのように表示させます。
Web Componentsなどでコンポーネントを関数から呼び出す方法では、分割されたコンポーネントを関数としてJavaScriptファイル化(CSSごと)し、そのJavaScriptファイルをクライアント側からfetchして実行することで一つのアプリケーションとして動かします。ReactやVueなどJavaScriptでアプリを管理している場合も、バンドルしたJavaScriptファイルをfetch&実行して一つのアプリケーションとして動かせます。この方法はマイクロフロントエンドの文脈でランタイム統合(またはアプリケーションシェル)と呼ばれています。
サーバーサイド組成パターン(エッジサイド組成パターン)
サーバーサイド組成パターン(サーバーサイドコンポジションとも呼ばれる)では、SSR(Server Side Rendering)やSSI(Server Side Includes)などの方法で、クライアントアプリケーションの配信時に、サーバー側でクライアントアプリケーションの配信ファイルにフラグメントのコードを埋め込みます。こうすることでクライアント側で実行されると一つのアプリケーションとして動作します。
ビルドタイム組成パターン
ビルドタイム組成パターンは、各フラグメントをバンドル&パッケージ化し、クライアントアプリをビルドする時に各フラグメントのパッケージを読み込んでバンドルすることで、一つのアプリケーションとして動かせるようにする方法です。Module Federationというバンドル方法やBit.devといったサービスなどが使われます。
各組成パターンのメリットデメリット
こちらのサイトのまとめがわかりやすかったです。本記事では紹介したサイトの内容を表形式にしたものを載せておきます。紹介した記事では組成に使える技術の紹介もあるのでご覧ください。
また別の記事では実装難易度や拡張性などの観点からメリット・デメリットを紹介しており、こちらの内容も大変興味深かったため共有しておきます。
実装の注意点
ここまで、アプリケーションを分割・統合する方法について述べてきましたが、ここでは分割統合するにあたって実装上考慮すべきポイントについて述べていきます。
こちらの記事によると、考慮すべき要素は下記のリストのようになっています。
マイクロサービス間のイベント伝播
データ共有
モジュール共有
ルーティング
キャッシュ
認証
計測
これらの要素を見てわかるように、コンポーネント内で物事が完結しないほとんどの要素の実装が考慮の対象となります。また、別途記事を書いて詳細を共有しようと思いますが、先ほど述べたアプリケーションの分割方法と組成方法、また利用するフレームワークやライブラリによって実装が難しい部分が異なります。その上で、利用ライブラリやそのバージョンなどが変わっていく中、構築するだけではなく健全に開発を進めアプリケーションが正常に動作する状態を維持する必要もあります。
自分がマイクロフロントエンドの構築を検証したときは、Web Componentsの仕様とライブラリの仕様が噛み合わずうまくstyleが適用されない、routerがラッパーされているためうまく直接router間で遷移情報をやりとりすることができないといった問題に直面しました。なんとか実装はできるものの、これをメンテナンスしていくことを考えると簡単には手出しできないという印象を抱きました。
もちろん、このような苦しみを避けるために便利なマイクロフロントエンド用のライブラリなども開発されていますが、どのような問題に遭遇するかを実際に体感した経験からすると、手を出しにくい印象を受けました。ライブラリに頼らず一度マイクロフロントエンドを構築してみると、難しさが体感できると思います。自分はReact, Vue, Nuxtで各フラグメントを構築しマイクロフロントエンドとして組み立てる検証をしました。
ライブラリや周辺技術
マイクロフロントエンドの調査中に調べた中で、いくつか気になったライブラリや技術に関するサイトを組成方法ごとにまとめておきます!
ビルド統合
Bit.dev
補足:サービスとして提供されており、バージョン管理もできます
Module Dederation
補足:Webpackを初め、Viteでもプラグインを使って実現できます
クライアント統合
frintls
single-spa
補足:マイクロフロントエンドと調べると便利なライブラリとしてよく紹介されています
luigi
mashroom
hinclude
Web Components (ShadowDOM)
https://developer.mozilla.org/ja/docs/Web/API/Web_components
補足:Webの標準技術で、結構面白い仕組みです
サーバーサイド統合
Tailor
Ara-Framework
Podium
補足:サーバーサイド統合で主に使われているライブラリです
SSI (Server Side Include), ESI (Edge Side Include)
おわりに
今回は前回の記事「マイクロフロントエンドについて調査したのでまとめてみた[概念編]」に引き続き、実装手段や考慮すべき事項など主に実装方法についてまとめました。
次回があれば、実際にクライアント統合でマイクロフロントエンドを実装してみてわかった知見についてまとめたいと思います。
いいね・シェア等があれば励みになりますので何卒...
では、また!
See you again! Have a nice day!
▼ワンキャリアのエンジニア組織のことを知りたい方はまずこちら
▼カジュアル面談を希望の方はこちら
▼エンジニア求人票