Microfrontends
Build large apps as independent, deployable modules.
What Are Microfrontends?
Microfrontends break large apps into smaller, independent pieces that can be developed and deployed separately.
Benefits
- Independent teams - Each team owns their module
- Different technologies - Use what works best for each module
- Independent deployment - Deploy modules without affecting others
- Scalable development - Add teams without coordination overhead
GoRouter Modular Approach
Each module is a mini-app with its own:
- Routes and pages
- Dependencies and services
- Business logic
- Event communication
Example Structure
class AppModule extends Module {
@override
List<ModularRoute> get routes => [
// E-commerce module
ModuleRoute('/shop', module: ShopModule()),
// User management module
ModuleRoute('/users', module: UsersModule()),
// Analytics module
ModuleRoute('/analytics', module: AnalyticsModule()),
// Admin module
ModuleRoute('/admin', module: AdminModule()),
];
}Module Communication
Use events for cross-module communication:
// Shop module sends event
ModularEvent.fire(ProductAddedToCartEvent(productId: '123'));
// Analytics module listens (using EventModule)
class AnalyticsModule extends EventModule {
@override
void listen() {
on<ProductAddedToCartEvent>((event, context) {
trackEvent('product_added', event.productId);
});
}
}Team Organization
Team A: E-commerce
class ShopModule extends Module {
@override
List<ModularRoute> get routes => [
ChildRoute('/', child: (_, __) => ProductListPage()),
ChildRoute('/product/:id', child: (_, __) => ProductDetailPage()),
ChildRoute('/cart', child: (_, __) => CartPage()),
];
}Team B: User Management
class UsersModule extends Module {
@override
List<ModularRoute> get routes => [
ChildRoute('/', child: (_, __) => UserListPage()),
ChildRoute('/profile/:id', child: (_, __) => UserProfilePage()),
];
}Best Practices
- Clear boundaries - Define module responsibilities
- Event-driven communication - Avoid direct dependencies
- Shared design system - Consistent UI across modules
- Independent testing - Test each module separately
- Monitoring - Track module performance and errors
When to Use
✅ Good for:
- Large teams (10+ developers)
- Complex business domains
- Need for independent deployment
- Different technology requirements
❌ Avoid for:
- Small teams
- Simple applications
- Tightly coupled features
- Performance-critical apps
Real Example
// E-commerce app with microfrontends
class EcommerceApp extends Module {
@override
List<ModularRoute> get routes => [
// Product catalog (Team A)
ModuleRoute('/products', module: ProductsModule()),
// Shopping cart (Team B)
ModuleRoute('/cart', module: CartModule()),
// User accounts (Team C)
ModuleRoute('/account', module: AccountModule()),
// Order management (Team D)
ModuleRoute('/orders', module: OrdersModule()),
];
}Each team can work independently while the app works as a cohesive whole.