🧩

マイクロフロントエンドフレームワーク single-spa を使って異なるUIフレームワークを共存させる : その1

に公開

こんにちは、ebi_yuです。

今回は、2つの記事に分けて 「マイクロフロントエンドアーキテクチャ」「single-spaを使ったマイクロフロントエンドアーキテクチャの実装方法」 について解説していきます。

この記事ではその1として 「マイクロフロントエンドアーキテクチャとsingle-spaの概要」 について解説します。

マイクロフロントエンドアーキテクチャは、以下のような課題を解決できます。該当する課題がある方はぜひご参照ください。

  • 異なる複数のチームが「別々のUIフレームワーク(Vue.js/React/Angular)で作ったUIコンポーネント」を一つのWebサイトで統合して表示したい。
  • レガシーなUIフレームワークで書かれたサイトを、少しずつモダンなUIフレームワークに置き換えていきたい。

概要

  • マイクロフロントエンドアーキテクチャとは フロントエンドアプリケーションを複数の「UIコンポーネントやロジックの単位の小さなアプリケーション」に分割して開発・運用するアーキテクチャです
  • マイクロフロントエンドアーキテクチャを採用することで 「異なるUIフレームワークの共存」「UIコンポーネント単位での責任分離」「UIコンポーネントの再利用」 が可能になります
  • single-spaとは マイクロフロントエンドアーキテクチャを実現するためのJavaScriptフレームワークです
  • single-spaは大きく 「ルートアプリケーション(root-config)」 と、「ルートアプリケーションに読み込まれる子アプリケーション(microfrontend)」 で構成されます
  • 子アプリケーション(microfrontend)には UIコンポーネント単位で分割した「Application」「Parcel」 と、ロジック単位で分割したUIを持たない「Utility」 があります

マイクロフロントエンドアーキテクチャとは

マイクロフロントエンドアーキテクチャとは、フロントエンドアプリケーションを複数の小さなアプリケーションに分割して開発・運用するアーキテクチャです。

マイクロと聞くと「マイクロサービス」を思い浮かべる方も多いかと思います。
お察しの通り、マイクロフロントエンドアーキテクチャはマイクロサービスの考え方をフロントエンドにも適用したアーキテクチャです。

従来のフロントエンドアプリケーションでは、「アプリケーションで動作する全てのコードを1つのリポジトリに含める」モノリシック構成が一般的でした。この構成は「全てのコードが一つのリポジトリに含まれるため管理が楽」というメリットがあります。
小さなプロジェクトではこの構成が問題になることはないでしょう。

しかし、プロジェクトが拡大しアプリケーションがより複雑になった場合はどうでしょう?
アプリケーションの複雑度が増すと、学習コストが増加するだけではなく、「ビルド時間やデプロイ時間の増加」「バンドルサイズの肥大化」 などのパフォーマンスの問題が発生します。
また、複数のチームで分担して開発するようになると、「他のチームの変更が自分のチームの作業に影響を与えることが増え、デプロイ調整コストが増加」 します。
さらに、モノリシック構成では 「UIフレームワークの共存が難しい」 ため、機能を実現するための最適なUIフレームワークを選べないという問題が起きるかもしれません。

このような課題を解決するために、マイクロフロントエンドアーキテクチャが提案されました。
マイクロフロントエンドでは、フロントエンドアプリケーションを「UIコンポーネントやロジックの単位」で別々のアプリケーションとして分割し管理します
これにより、「複数のチームが各コンポーネントを独立して開発・デプロイできる」ようになり、「コードの複雑化を抑え、バンドルサイズの最適化が可能」 になります。

また、マイクロフロントエンドアプリケーションの管理に 「モノレポ構成(複数のプロジェクトを1つのリポジトリで管理する構成)」 を採用することで、「アプリケーションで動作する全てのコードを1つのリポジトリに含める」というモノリシック構成のメリット を享受しつつ、マイクロフロントエンドのメリットを享受することができます。

マイクロフロントエンドアーキテクチャのメリット

以下にマイクロフロントエンドアーキテクチャの主なメリットを挙げます。

1. 独立性

それぞれのアプリケーションが独立しているため、自チームの変更が他のチームに影響を与えることが少なくなります。

  • 独立したデプロイ: 他のチームの作業を待つことなく、自分たちのセクションを更新できる
  • 技術選択の自由: 異なるフレームワークやライブラリを使用できる(互いに影響しない)
  • チーム間の依存関係の削減: 各チームが自律的に作業できる

2. スケーラビリティ

一つのアプリケーションの責任の範囲が小さくなるため、効率的なチーム分割が可能です。

  • 小さなチームでの管理: アプリケーションを小さな部分に分割し、複数の小さなチームで管理
  • 専門性の向上: 各チームが特定の機能やページに集中できるため、生産性が向上
  • 並行開発: 複数のチームが同時に異なる機能を開発できる

3. 保守性とアップデートの容易さ

それぞれのアプリケーションが独立しているため、変更による副作用やデグレード(品質低下)を最小限に抑えられます。

  • 小さなコードベース: 理解、テスト、デバッグが容易
  • 段階的な技術移行: 新しい技術への移行や既存コードの更新が、アプリケーション全体に影響を与えずに実行可能
  • リスクの局所化: 変更の影響範囲が限定される

4. 再利用性

開発したアプリケーションを、他のプロジェクトでも活用できます。

  • コンポーネントの共有: 他のプロジェクトやチーム間でコンポーネントを再利用
  • 開発効率の向上: 既存の資産を活用した迅速な開発

5. 耐障害性

一部のアプリケーションに障害が発生しても、アプリケーション全体への影響を最小限に抑えられます。

  • 部分的な障害の隔離: 1つのマイクロフロントエンドの問題が他に波及しない
  • グレースフルデグラデーション: 一部機能が停止しても、他の機能は正常に動作

マイクロフロントエンドアーキテクチャのデメリット

マイクロフロントエンドアーキテクチャを採用すると、1つのアプリケーション単位での複雑さは減少しますが、システム全体としての複雑さは増加します。

1. 複雑性の増加

モノリシックなアプリケーションに比べ、アーキテクチャが複雑になります。

  • 統合の複雑さ: 異なるアプリケーション間での統合と通信の管理が複雑
  • 管理責任の複雑化: 複数のアプリケーションが存在するため、全体の管理責任が不明確になる可能性
  • 学習コストの増加: 新しいアーキテクチャパターンの理解が必要

対策

  • CustomEventなど疎結合な通信を使う
  • 責任範囲をドキュメント化し、組織的に管理する

2. パフォーマンスの懸念

リソースの重複や非効率な読み込みが発生する可能性があります。

  • 重複する依存関係: 各マイクロフロントエンドが同じライブラリを個別に読み込む可能性
  • ネットワークリクエストの増加: 複数のアプリケーションを読み込むため、リクエスト数が増加
  • 初期読み込み時間の増加: 複数のバンドルを読み込む必要がある

対策

  • import-mapで複数のマイクロフロントエンドで同じ依存関係を使う
  • 遅延読み込みやプリフェッチ、HTTP/2通信の最適化などのネットワーク戦略を取る

3. セキュリティリスク

独立したアプリケーション間でのデータ管理が複雑になります。

  • 認証・認可の管理: 複数のアプリケーション間での一貫した認証管理が困難
  • データの整合性: アプリケーション間でのデータの流れの管理が複雑
  • セキュリティポリシーの統一: 各アプリケーションで一貫したセキュリティ対策が必要

対策

  • 認証・認可: SSOやOIDCなど共通基盤を利用

4. デプロイメントの複雑化

複数のアプリケーションのデプロイメントを統合して管理する必要があります。

  • デプロイメントプロセス: 複数のマイクロフロントエンドの協調したデプロイが必要
  • モニタリング: 各アプリケーションの状態を個別に監視する必要
  • デバッグの困難さ: 問題の原因特定が複数のアプリケーションにまたがる場合がある

対策

  • カナリアリリースやブルーグリーンデプロイなどの戦略を利用
  • GrafanaやKibanaなどで一元的にモニタリング

single-spaとは

JavaScriptで書かれた「マイクロフロントエンドフレームワーク」です。
以下の機能を提供します。

  • マイクロフロントエンド機能 : 異なるフレームワークを同一ページ内で共存させ、それぞれが独立して管理することが可能です。
  • ルーティング管理 : URLの変更に応じてアクティブなアプリケーションを決定し、複数のアプリケーション間でのナビゲーションを制御します。
  • ライフサイクル管理 : 各アプリケーションの初期化(bootstrap)、DOMへのマウントやアンマウント(mount/unmount)、更新(update)を管理します。

https://single-spa.js.org/

single-spaの構成

single-spaは大まかに、「ルートアプリケーション(root-config)」 と、「ルートアプリケーションに読み込まれる子アプリケーション(microfrontend)」 で構成されています。

ルートアプリケーション(root-config)

single-spaで管理したいマイクロフロントエンドアプリケーションを起動するためのルート構成です。
単一のhtmlファイルとスクリプトファイルで構成されます。

主な役割

  • single-spaにマイクロフロントエンドを登録する
  • single-spaライブラリを起動する

子アプリケーション(microfrontend)

single-spaによって管理されるJavaScriptモジュールです。
マイクロフロントエンドには以下の三つの種類があります。

  • Application : 特定のURL(route)にアクセスしたときにレンダリングされるコンポーネント
  • Parcel : ページのURLに依存せず、レンダリングされるコンポーネント
  • Utils : コンポーネントをレンダリングせず、JavaScript ロジックを共有する

Application/Parcel/Utilsの比較

以下にそれぞれの違いをまとめます。
基本的にはApplicationを使い、必要に応じてParcelやUtilsを使うとよいでしょう。

機能 Application Parcel Utility
ルーティング ルーティングによる起動制御ができる できない できない
UIレンダリング される される ロジックだけ含めてUIを含めないこともある
ライフサイクル single-spaで管理されるライフサイクル カスタム管理されたライフサイクル 直接のsingle-spaのライフサイクルなし
いつ使用するか マイクロフロントエンドアプリケーションの作成 複数のマイクロフロントエンドアプリケーション内で共用されるコンポーネントを作成したい場合 ロジックのみをアプリケーション間で共有したい場合

まとめ

この記事では 「マイクロフロントエンドアーキテクチャとは何か」「single-spaの概要」 について解説しました。

  • マイクロフロントエンドアーキテクチャを採用することで、「異なるUIフレームワークの共存」「UIコンポーネントの独立性向上」「UIコンポーネントの再利用」 が可能になります。
  • single-spaは 「マイクロフロントエンドアーキテクチャを実現するためのJavaScriptフレームワーク」 であり、「ルートアプリケーション(root-config)」とルートアプリケーションに読み込まれる「子アプリケーション(microfrontend)」 の2つの要素で構成されます。
  • 子アプリケーション(microfrontend)にはUIコンポーネント単位で分割した「Application/Parcel」 と、ロジック単位で分割したUIを持たない「Utility」 があります。

次回の記事では実際にsingle-spaを使ってマイクロフロントエンドアプリケーションを作成する方法について解説します。

https://zenn.dev/ebi-yu/articles/9aca505bfba289

Discussion