Micro Frontends を学んだすべて
Micro Frontends という Web フロントエンドアーキテクチャがあります。 このアーキテクチャを知るために、書籍を読み、簡単なサンプル Web アプリを開発しました。 そこから学んだことをすべて議事録として残したいと思います。
モノリシックな Web アプリケーション
マイクロサービスという考え方の多くは、バックエンドへ適用されることが一般的です。 一方で、フロントエンドは依然モノリシックなままの状態です。
EC サイトのような Web アプリケーションでは、様々な専門知識(商品、注文、検索など)を必要とし、フロントエンド開発者の守備範囲がとても広くなってしまいます。 開発者には限界があり、いつしかトラブルシューティングに追われる日々になってしまいます。
そこで、Micro Frontends というアーキテクチャの出番です。
Micro Frontends とは
それはマイクロサービスの考え方をフロントエンドに拡張したものです。
※ https://micro-frontends-japanese.org
要は、バックエンドだけでなく、バックエンドからフロントエンドまでをマイクロサービス化することです。
さらに詳しく知りたい方は、次のページをご参考下さい。とてもわかりやすいです。
https://micro-frontends-japanese.org/
また、次の書籍を読むと、 https://www.manning.com/books/micro-frontends-in-action
Amazon does not talk a lot about its internal development structure. However, there are reports that the teams who run its e-commerce site have been working like this for a long time. ...
Micro frontends are indeed quite popular in the e-commerce sector. In 2012 the Otto Group, a Germany based mail order company and one of the world’s largest e-commerce players started to split up its monolith. ...
The Swedish furniture company IKEA and Zalando, one of Europes biggest fashion retailers, moved to this model. ...
But micro frontends are also used in other industries. Spotify organizes itself in autonomous end-to-end teams they call Squads. ...
Excerpt From: Michael Geers. “Micro Frontends in Action MEAP V03.” iBooks.
という内容があります。
IKEA や Zalando といったEC サイトが Micro Frontends を採用するケースが多く、公には言っていませんが、Amazon も Micro Frontends で取り組んでいるようです。 EC サイトだけでなく、Spotify のようなサービスにも適用されるケースがあります。
Micro Frontends の良さ
私が思う Micro Frontends から得られる最大の恩恵は、"局所化" だと思います。
フロントエンドをサービス毎(商品、注文、検索など)に分割することで
- サービスの専門性向上
- ex. 対象サービスのフロントエンドだけに集中できる
- サービスの開発速度向上
- ex. 対象サービスのソースコードだけ読めば良い
- ex. 対象サービスだけにライブラリアップデートすれば良い
- ex. フレームワークの切り替えは対象サービスだけすれば良い
少し薄っぺらいかも知れませんが、↑ のように実感しています。
※ Micro Frontends は Web ベースのアーキテクチャになります。
Micro Frontends の難しさ
ここは、まだちゃんと掘り下げれていませんが、次のようなものがあります。
- 特定チームが改善しても、チーム全体が改善しない
- ex. あるチームが webpack のビルド時間短縮に成功しても、他のチームは影響を受けない
- ex. 全てのチームが採用しているライブラリのセキュリティパッチは、それぞれのチームが更新しなければならない
- チーム全体へ共有する仕組みを考える必要がある
- ex. デザインシステム、パフォーマンス、ナレッジ
- エッジな技術スタック採用は、チームメンバー移動を困難にする
- ex. パラダイムシフトが発生してしまう 技術スタック
Micro Frontends の作る上で考えること
フロントエンドをマイクロサービス化するということは、各サービスで HTML/CSS/JS を作ることになります。 それらのサービスを統合するサービスが重要になってきます。
大きく分けて 2 つの統合パターンがあります。
種類 | 解決手段 | メリット | デメリット |
---|---|---|---|
サーバーサイド統合 | SSI, ESI, Tailor, Podium | ・SEO 対策上良い ・ユーザーのネットワークレイテンシーが少ない ・初回ロードパフォーマンスが優れている | ・インタラクションアプローチが不得意 |
クライアントサイド統合 | ・Web 標準 ・シャドウ DOM による堅牢な作り | ・サポートブラウザに依存する ・クライアント側の JavaScript が有効であること |
また、これら 2 つの選択基準は次のようになります。
種類 | 選択基準 |
---|---|
サーバーサイド統合 | 良好な読み込みパフォーマンスと検索エンジンのランキングがプロジェクトの優先事項であること |
クライアントサイド統合 | さまざまなチームのユーザーインターフェイスを 1 つの画面に統合する必要があるインタラクティブなアプリケーションを構築すること |
今回、私はサーバーサイド統合(Podium)を選択しました。 ただ、インタラクティブなアプローチも必要だったため、Hydrationを使いました。
Hydration refers to the client-side process during which Vue takes over the static HTML sent by the server and turns it into dynamic DOM that can react to client-side data changes.
※ https://ssr.vuejs.org/guide/hydration.html
Hydration は、サーバーサイドでレンダリングした静的 HTML に、クライアントサイドの動的レンダリングができるようにするようなものです。
※ クライアントサイド統合(Web Components)でも良かったのですが、私都合により却下となりました。
Micro Frontends サンプル Web アプリ
apple, banana, orange という商品を検索するだけのサンプル Web アプリを作りました。
概要図はこちらです。
サンプルコードは、ここに置いています。 https://github.com/silverbirder/micro-frontends-sample-code
サービス
サービス | 役割 | JS フレームワーク |
---|---|---|
team-search | 商品を検索するサービス | Vue.js |
team-product | 商品を表示するサービス | React.js |
team-page | サービスを統合するサービス | フレームワーク未使用 (Node.js) |
仕組み
Podium というライブラリを採用しました。
https://github.com/podium-lib/
これは、フロントエンドのサービスを簡単に統合できるようなライブラリになっています。 Podium には大きく分けて 3 つの機能があります。
- @podium/podlet
- ページフラグメントサーバーを構築する
- ex. team-search, team-product
- @podium/layout
- Podlet を集めて、ページ全体のレイアウトを構築する
- ex. team-page
- @podium/browser
- ブラウザベースの機能を提供する
- MessageBus による Podlet 同士のコミュニケーション
- ex. team-search, team-product で publish/subscribe
@podium/podlet
Podlet には、manifest.json と呼ばれる値を返却することが必須になっています。 menifest.json には、サービスのエンドポイントや、Asset(JS や CSS)のパスが明記されています。
team-search では
$ curl https://team-search.fly.dev/manifest.json | jq .
{
"name": "search",
"version": "1.0.0",
"content": "/",
"fallback": "",
"assets": {
"js": "/search/static/fragment.js",
"css": ""
},
"css": [],
"js": [
{
"value": "/search/static/fragment.js",
"async": true,
"defer": true,
"type": "default"
}
],
"proxy": {}
}
というレスポンス結果になります。
@podium/layout
Layout では、Podlet の manifest.json の定義に従って fetch することになります。
team-page では
// server.js (express)
app.get(`/`, async (req, res) => {
const incoming = res.locals.podium;
const [searchBox] = await Promise.all([
podletSearch.fetch(incoming, { pathname: "/search/box", query: req.query }),
]);
const [items] = await Promise.all([
podletProduct.fetch(incoming, {
pathname: "/product/items",
query: { id: searchBox.headers["x-product-items"] },
}),
]);
res.podiumSend(`
<html>
<head>
<title>Shop</title>
${searchBox.js.map((js) => js.toHTML())}
${items.js.map((js) => js.toHTML())}
</head>
<body>
<div id="app-shell">
${searchBox.content}
${items.content}
</div>
</body>
</html>
`);
});
のように Podlet を使って、ページ全体を構築します。このようにサーバーサイドで統合しています(SSR)。 しかし、インタラクティブなアクションも必要なため、Podlet から Hydrate するための js を読み込んでいます。
また、team-search の検索結果(x-product-items)を team-product へ渡しているため、商品の検索結果を含めて SSR が実現できます。
@podium/browser
サーバーサイドは、podium/podlet, podium/layout で連携できます。 クライアントサイドは、この @podium/browser の MessageBus で連携できます。
今回のサンプル Web アプリでは、次のようなユースケースに使用しています。
- ユーザーが検索ボックスにキーワードを入力する
- team-search がキーワードから商品を検索する
- team-search が 2 の結果を publish する
- team-product が 3 を subscribe し、商品を更新する
// team-search.js
messageBus.publish("search", "search.word", { items: hitItems });
// team-product.js
messageBus.subscribe("search", "search.word", (event) => {
hydrate(
<Items {...{ items: event.payload.items }} />,
document.querySelector("#team-product-items")
);
});
このようにすることで、画面更新ではなく部分更新ができました。 インタラクティブな操作も実現可能です。
状態管理, ルーティング
ここは、まだきちんと作っていませんが、次のようなコンセプトで設計するのが良いと思います。
- 状態管理
- 各サービスが状態管理する。状態は共有しない。
- 統合サービスが共通的な状態を管理する。
- ルーティング
- 各サービスが query を設定する。
- 統合サービスが URL パスを管理する。
その他
各サービスは、fly.io という PaaS へデプロイしています。
CDN で SSR が実行できる Edge Workerを使用しています。 これにより、SSR 結果をキャッシュし、高速にレスポンスを返却できます。
ただ、サンプル Web アプリでは、全くその力を引き出せていないです...
※ 参考記事 https://mizchi.hatenablog.com/entry/2019/02/21/235403
サンプル Web アプリで分かったこと
SSR + CSR (Hydration) が実現可能
サーバーサイド統合であっても、CSR は実現可能です。 ただし、Hydration には パフォーマンス面に難有りなため、このあたりは課題として残ります。 また、CSR するための bundle した javascript の size には注意が必要です。
例えば、次のリポジトリにある "shared_vendor_webpack_dll" のように、vendor ファイルを共有することで、 javascript の size を減らすといった手段があります。
https://github.com/naltatis/micro-frontends-in-action-code
また、次のリポジトリにある zalando tailor は、script load を streaming することで、 全体の script load 完了時間を短縮するツールもあります。
https://github.com/zalando/tailor
サービス内で技術スタックを選択できる
マイクロサービスでは、よくあるメリットとして挙げられるものです。 フロントエンドでも、同様に技術スタックを自由に選択できます。
今回では、React.js と Vue.js を使用しています。 これを Riot.js や Svelte.js にも切り替えることも可能です。
フロントエンド界隈では、JS フレームワークの変化が激しいので、 このメリットは大切だと思います。
ただし、Podium の manifest.json を返却しなければなりません。 今の所、Podium に対応しているのは Express のみなので、Express を使用する フレームワークのみとなります。
サービス毎のフロントエンドに集中できる
検索サービスだと、検索に特化したフロントエンドのみに集中することができます。 商品サービスだと、商品の表示内容のみに集中することができます。
ただ、どうしても他サービスと連携する要件が出てきます。 これは、マイクロサービスとしての難しさだと思います。 例えば、各サービスがどのタイミングでイベント登録するのかを考える必要があります。
最後に
EC サイトのようなアプリケーションでは『商品を探しやすくする』『買いたくなるような商品を表示する』 『商品を簡単に購入できる』などフロントエンドでやるべきことが多くあります。
そういうサービスにおけるフロントエンドがモノリシックであれば、 統一性が欠けてしまったり、知らぬ間にバグを埋め込んでしまうケースが発生してしまいます。
Micro Frontends は、このような複雑化するフロントエンドにメスを入れる良いアーキテクチャだと思います。 ただし、バックエンドにおけるマイクロサービス化による課題があるように、フロントエンドにおける マイクロサービス化にも課題はあるはずです。
日本では、Micro Frontends の導入実績が少なく、まだまだ発展途上だと思います。 この記事が、どこかのサービスへの参考になればと思います。
最後まで読んで頂き、ありがとうございました。
参考リンク
Tags
2022-11-13
DAZN の Luca Mezzalira さんが書かれたマイクロフロントエンドを読みました。簡単な書籍レビューを残しておこうかなと思います。...
2022-05-28
Micro Frontends(以降、MFE)で組成するフラグメントを Web Components で定義して Module Federation で共有する方法を、ざっくり紹介します。...
2021-01-16
2021年、あけましておめでとうございます。本年も宜しくおねがいします。最近、体重が増えてしまったため、有酸素運動を頑張っています。本記事は、昨年の冬あたりから検証していた クライアントサイド統合でのMicro Frontendsについて話そうと思います。検証したソースコードは、次のリポジトリにあります。...
2020-11-19
Micro Frontends とは?皆さん、**Micro Fronends**(以下、MFE)をご存知でしょうか。説明をざっくりしますと、Microservicesの考え方をフロントエンドまで拡張した考え方です。Microservicesは、バックエンド側で適用される事例をよく耳にしますが、フロントエンドでの適用事例は、あまり聞いたことがありません。...
2020-11-15
今回、またMicro Frontendsの構築を試みようと思います。構築パターンの内、サーバーサイド統合パターン、特にエッジサイド統合を試しました。その内容を紹介します。サンプルコードは、下記に残しています。...
2020-10-07
Micro Frontendsに関わる記事を100件以上読みました(参考記事に記載しています)。そこから得たMicro Frontendsについてこの投稿に記録します。また、調査メモについて、次のリポジトリに残しています。...
2020-10-04
Zalando社が開発したTailorを使って、サンプルWebアプリをMicro Frontendsで構築してみました。Tailorはサーバーサイドで統合するアーキテクチャです。クライアントサイドは、Web Componentsで作られているLit Elementを使って統合しました。どういった内容か、ここに投稿しようと思います。...
2020-08-23
みなさん、こんにちは。silverbirder です。、Micro Frontends があります。今、Ara-Frameworkというフレームワークを使った Micro Frontends のアプローチ方法を学んでいます。...
2021-08-28
TikTokへスクレイプするバッチをGCP上で構築しました。GCP構築のシステム設計話と、その構築時に、ハマったことを共有します。...
2021-05-24
Webフロントエンジニアたるもの、ブラウザの仕組みに興味を持つのは自然の摂理です。本記事では、私がブラウザの仕組みを学んでいく過程を備忘録として残します。...
2021-03-10
リモートワークが普及しつつある今、オンラインでの仕事に慣れているエンジニアも多いのではないでしょうか。私も、そのエンジニアの一人であり、約1年はリモートワークしています。そんな中、久々に会社へ出社すると、気軽に話しかける楽さ を実感しました。この体験について、深堀りしたいと思います。...
2020-10-29
私は、現在26歳のWebエンジニアです。これまでの技術に対する学び方と、これからの技術に対する学び方について、少し考えたいと思っています。...
2020-10-07
Micro Frontendsに関わる記事を100件以上読みました(参考記事に記載しています)。そこから得たMicro Frontendsについてこの投稿に記録します。また、調査メモについて、次のリポジトリに残しています。...
2020-06-06
みなさん、Zoom使っていますか? ZoomのMeetingを自動生成するGASライブラリを公開しましたので、そのきっかけと使い方について紹介しようと思います。...
2020-06-04
GoogleやGithubなど、様々なサービスのプロフィール情報(画像, etc)を一括更新するツール、puppeteer-account-manager を開発しました。開発の目的や、開発から得た知見を紹介します。...
2020-03-15
Twitterに投稿されているLinkを収集するツール Cotlin を作りました。Collect links in tweet から、Cotlinという名前にしました。Androidのアレに似ています。...
2020-02-24
Google Apps Script (以下、GAS)で、困ったことがあったので備忘録として残しておこうと思います。...
2020-02-17
ターゲットユーザー * GMailとGCalendarを使っている人 メールを開くって面倒じゃないですか? 例えば、次のようなメールを受信していたとします。* アマゾンで商品を購入した際、お届け予定日が記載されたメール * 映画館(TOHOシネマ)でネット予約した際、上映日が記載されたメール * ホテルをネット予約した際、宿泊日が記載されたメール...
2020-02-08
画像で会話って楽しい 皆さん、チャットツールでコミュニケーションするとき、絵文字や画像って使ってますか?僕はよく使ってます。人とコミュニケーションするのに、文字だけだと堅苦しいイメージですよね。例えば、『OKです、それで先に進めて下さい。』というフレーズだけだと、相手がどのような感情なのか読み取りにくいです。...
2019-10-27
2019年10月11日~2019年10月15日の5日間、フィリピンに行ってきました。日本人男性(前職の先輩:Kikuchi)とフィリピン人女性が結婚するため、その結婚式旅行に同伴させて頂きました。Kikuchiさんとは、私が新人の頃に大変お世話になった方なので、お祝いの気持ちが込み上げてきました。:)...
2019-09-06
技術書典7で初執筆しました。記事の目的 * 執筆でどういったことをしたのかの備忘録 * 執筆を考えている人の助けになりたい実際に販売する本は↓のものです。...