![見出し画像](https://assets.st-note.com/production/uploads/images/168966919/rectangle_large_type_2_f377c186c130b529140c4098a0f653d5.png?width=1200)
第五回:マイクロフロントエンドのルーティング戦略
「別々のアプリなのに、URLは一つにまとめたい...」
「戻るボタンを押すと変な動きをしてしまう...」
「アプリ間の画面遷移がスムーズにいかない...」
マイクロフロントエンドでよく悩むのが、画面遷移の処理です。今回は、実装例を交えながら、効果的なルーティング戦略を見ていきましょう。
まず、何が難しいの?
従来のSPA(シングルページアプリケーション)では
// React Routerの例
function App() {
return (
<Router>
<Route path="/products" component={ProductList} />
<Route path="/cart" component={Cart} />
</Router>
);
}
これが当たり前でしたが、マイクロフロントエンドでは
商品一覧アプリ(React Router)
└── /products
カートアプリ(Vue Router)
└── /cart
注文アプリ(独自ルーティング)
└── /orders
異なるアプリが、それぞれ独自のルーティングを持っています。これをどうまとめるか?というのが課題です。
3つの主要な実装パターン
1. 集中型ルーティング
メインのアプリ(コンテナ)で全てのルーティングを管理する方法です。
// コンテナアプリ
const routes = {
'/products': () => loadApp('products'),
'/cart': () => loadApp('cart'),
'/orders': () => loadApp('orders')
};
function handleNavigation(path) {
const route = routes[path];
if (route) route();
}
// URL変更を監視
window.addEventListener('popstate', () => {
handleNavigation(window.location.pathname);
});
メリット
URLの管理が簡単
画面遷移の制御が容易
SEO対策がしやすい
デメリット
各アプリの自由度が低下
設定が中央集権的に
2. 分散型ルーティング
各アプリが独自のルーティングを持つ方法です。
// 商品一覧アプリ(React)
function ProductApp() {
return (
<Router basename="/products">
<Route path="/list" component={ProductList} />
<Route path="/detail/:id" component={ProductDetail} />
</Router>
);
}
// カートアプリ(Vue)
const router = new VueRouter({
base: '/cart',
routes: [
{ path: '/items', component: CartItems },
{ path: '/checkout', component: Checkout }
]
});
メリット
各アプリの独立性が高い
開発の自由度が高い
スケーラビリティが良い
デメリット
アプリ間の連携が複雑に
全体の一貫性を保つのが難しい
3. ハイブリッド型
メインの遷移はコンテナで管理し、詳細な遷移は各アプリに任せる方法です。
// コンテナアプリ
const mainRoutes = {
'/products': ProductApp,
'/cart': CartApp,
'/orders': OrderApp
};
// 商品一覧アプリの中での遷移
function ProductApp() {
return (
<Router basename="/products">
<Route path="/list" component={ProductList} />
<Route path="/detail/:id" component={ProductDetail} />
</Router>
);
}
実践的な実装例
実際のプロジェクトでよく使う実装例を見てみましょう
// イベントベースのルーティング連携
class RouterEventBus {
constructor() {
this.listeners = [];
}
// 画面遷移をリッスン
listen(callback) {
this.listeners.push(callback);
}
// 画面遷移を通知
notify(path) {
this.listeners.forEach(callback => callback(path));
}
}
const routerBus = new RouterEventBus();
// 商品一覧アプリ
function ProductApp() {
useEffect(() => {
routerBus.listen((path) => {
if (path.startsWith('/products')) {
// 商品一覧アプリの処理
}
});
}, []);
return <ProductRouter />;
}
トラブルシューティング
よくある問題と解決策
1. 戻るボタンの問題
// 履歴の状態を管理
window.addEventListener('popstate', (event) => {
if (event.state && event.state.app) {
// アプリ固有の履歴処理
handleAppSpecificNavigation(event.state);
}
});
2. アプリ間のデータ受け渡し
// URLパラメータを使う
function navigateToCart(productId) {
const url = `/cart?product=${productId}`;
window.history.pushState({}, '', url);
routerBus.notify(url);
}
まとめ
ルーティング戦略は、プロジェクトの規模や要件によって選択しましょう
小規模なら集中型
大規模なら分散型
中規模ならハイブリッド型
次回は、もう一つの大きな課題である「状態管理」について詳しく見ていきます。