[翻訳記事] AWSで作る、マイクロフロントエンドアーキテクチャ構築

※こちらの記事は、元ネタの翻訳＆サマリーとなっております。
詳細は元ネタをどうぞ。

元ネタ
[AWS기반 마이크로 프론트엔드 아키텍처 구축하기　（YouTube）](https://www.youtube.com/watch?v=FUPlSphkPPs)

----

## マイクロフロントエンドとは？

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/53617faa-dd13-25b2-cb9d-b278044e942c.png" width="500px"/>

> 個別に開発・デプロイ可能な、複数の小さなWEBアプリケーションを組み合わせて、一つのWEBアプリケーションを作る開発方法論


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/b182efc4-b8ed-cc74-b1d8-76b16f0ce7c7.png" width="500px" />

例：ECサイト
> 商品検索ページがあったとして、それを検索と詳細ページに分離し、合計3つのアプリケーションを作ることができるということ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/0dd9ce5c-8629-4935-be8a-459f7a8c9631.png" width="500px" />

マイクロフロントエンドとは？  
次のように定義されている

> 独立したTeam毎に開発したpictureの組み合わせとしてアプリケーションを俯瞰するものであり、各Teamsは各々が属すミッションとビジネスドメインがありEnd-to-Endで開発する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/c3effd52-4c4b-f436-fd14-41b1a378a049.png" width="500px" />

マイクロフロントエンド登場背景  
> モノリシックフロントエンドを解決するために登場した

- 増加するビルドおよびデプロイ時間
- モジュール間結合度増加
- 蓄積されるレガシーコード
- 更新の難しい、依存性ライブラリ


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/0bc376cb-ffd2-5fc2-2a5e-e89f2f21ae4e.png" width="500px" />

マイクロフロントエンドの長所
- より小さく凝集度の高いコードベースとなる
  - 早いビルド/デプロイ時間
  - 運用が楽
- アプリケーションをより簡単に更新できる
- 独立的なデプロイが可能
- Team間の疎結合化、各Teamがより自由に意思決定できる


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/8d908b99-23af-d48b-03bc-454612c1bfb5.png" width="500px" />

マイクロフロントエンドの短所
- 依存性の重複により使用者がより多くのbundleをダウンロードする可能性がある
- さらに多くの開発および運用コストがかかる
- 複数のアプリケーション間で一貫したUXを提供することが難しい

> これら短所をうまくコントロールすることが鍵

## マイクロフロントエンドアーキテクチャ構築方法

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/418dead2-3f5e-0fb1-0298-2f734179bc22.png" width="500px" />

> アプリケーションの組み合わせ型で2つに分類される

#### Build-time composition
- Build時に全てのBundleを読み込む
- shared library (ex. npm package)

#### Run-time composition
- Client-side composition (JS実行時に各コンポーネントを読み込む)
  - ユーザーのブラウザ上
  - **Webpack 5 Module Federation**
- Edge-side / Server-side composition
  - EC2とかECRとかLambda Edgeとか


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/15899c0d-44c5-eb39-db02-5ebe4780769d.png" width="500px" />

- すべてのアプリケーションはコンテナ
  - Host / Remote コンテナで区分
- Hostコンテナ　＝　利用側
  - RemoteコンテナのJSモジュールを呼び出し使用する側のコンテナ
- Remoteコンテナ　＝　配信元
  - JSモジュールを他のコンテナで使用できるようにexposeするコンテナ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/e35fbbc2-f922-8543-2bf3-bf135f34c69c.png" width="300px" />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/64066f03-9606-adc7-db39-e7b16beaaa35.png" width="300px" />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/67988f18-83be-7e13-0f94-4536fb01f36d.png" width="300px" />

それぞれが独立しているので、モジュール毎にFrameWorkも自由に選択できる


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/7c8d2673-e523-241b-1e43-6544066e4767.png" width="500px" />

デモのアーキテクチャ

> 開発はそれぞれ独立して、S3にソースコードをデプロイ

それぞれがブラウザで呼ばれて一つのアプリケーションになる

```
CDKの設計の説明があったが、ここは割愛
```


## 実際のプロジェクトのディレクトリ構成

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/1592c0de-6693-1cda-9d0f-5b425c6d1fd0.png" width="500px" />

- packagesの下に、アプリケーションが3つ
  - それぞれnpmのパッケージとして管理
  - app-hostがHostコンテナ
  - app-feed, app-orderがRemoteコンテナ
- cdkフォルダにはインフラコード
  - lambda edgeを説明
  - `/` のアクセスには、組み合わせたページを返せるように `/app-host/` をパスに追加してる
    - `/index.html` をさらに追記

#### app-hostアプリの説明
- package.jsonをちょっと見せて、Reactアプリであることを確認
- ページは2つ
- リストと詳細

ProductListPage
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/d8805036-7002-130e-3b33-8a04b862d262.png" width="400px" />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/11523127-a1ca-63b2-5152-9a51680125b3.png" width="400px" />
- モジュールを持ってきてmountして、
- 実際は、id="app-feed"にRenderingされる


ProductDetailPage
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/93f5f3d3-a6c3-b027-3657-a0a7476fcd2a.png" width="400px" />


webpack.configもみてみましょうー
- ModuleFederationPlugin
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/a5b74f61-4430-a633-183b-11312edf4512.png" width="500px" />

- remoteフィールドにどのRemoteコンテナを呼び出すのか定義できる
- getRemoteEntryは、dev, prodによってホスト名を localhostかCDKで作ったホスト名かを切り替えているだけなので気にしなくてよい


remoteEntry.js
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/e70d1fc9-cd88-2384-ee7e-dfd5f42df28f.png" width="400px" />

- どのモジュールを外部からアクセスできるようにするかをexposesに定義
- remoteEntry.jsがマッピングするのでこのファイルさえ読み込めればOK


## ここでLocalで実行してみるデモを実施


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/6d464299-4220-ea21-65f9-d19fc18bb81c.png)

左から順に3つのアプリケーションを立ち上げる
それぞれ、
- app-host
  - http://127.0.0.1:30000/
- app-order
  - http://127.0.0.1:30001/
- app-feed
  - http://127.0.0.1:30002/

app-host
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/bba98281-ae37-05a0-5910-85e2290f61ed.png" width="300px" />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/a29cdd8f-8024-a5bc-a51b-dff318d8c722.png" width="300px" />

app-order
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/4d48d1f9-da96-8157-8ebf-45a3bb23b3a2.png" width="300px" />

app-feed
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/d4c89b7d-5b5b-eda2-48ec-b52878bd2ec9.png" width="300px" />

それぞれ独立したアプリケーションであるため、それぞれのURLでも表示がされるのが確認できる


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/ea29b0e0-dfcb-f81b-6a48-a57517cecf23.png" with="500px" />

> CDKデプロイ後、サーバー配信をNetworkタブで確認してみる

https://{domain name}/
https://{domain name}/app-order/
https://{domain name}/app-feed/
それぞれモジュールが独立して動いてる。

Networkみてみると、それぞれの/remoteEntry.jsを読み込んでマッピングしている様子がわかる

## まとめ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/b489747d-5d13-bbb5-e4fc-04a73ab058ce.png" width="500px" />

||||
| --- | --- | --- | 
| Frontend | Team <br> **Feed** | Team <br> **Order** |
| Backend | service <br> **app-feed** | service <br> **app-order** |
| Data | mission <br> **滞在時間、CTR増加** | mission <br> **購買CVR増加** |


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/0095c50f-cba5-db75-ab20-d5cba8c6eb9a.png" width="500px" />

- マイクロフロントエンドは、複数のWEBアプリケーションを組み合わせて一つのWEBアプリケーションを作る方法論
- 各アプリケーションは独立して開発およびデプロイが可能
- Webpack 5 Module Federationを利用すれば、Client-side Compositionを簡単に作れる
- AWS S3、CloudFront、Lambda@Edgeを利用してCliend-side Compositionマイクロフロントエンドアーキテクチャを構築できる
- マイクロフロントエンドアーキテクチャはプロダクト開発領域だけではなく組織の構造にもポジティブな影響を与える


## ソースコード＆デモはこちら

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41763/b1f1c281-23d4-7d3a-f476-55d6a51b8c28.png" width="500px" />

デモのソースコードはこちら
Srouce code: [https://github.com/eunsukimme/micro-frontend-on-aws](https://github.com/eunsukimme/micro-frontend-on-aws)
DEMO URL: [https://dl120itgchg9q.cloudfront.net/](https://dl120itgchg9q.cloudfront.net/)