🏢 Micro Front Ends
🏢 Microfrontends

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

  1. Clear boundaries - Define module responsibilities
  2. Event-driven communication - Avoid direct dependencies
  3. Shared design system - Consistent UI across modules
  4. Independent testing - Test each module separately
  5. 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.