App Modularization
As Flutter applications scale across large engineering teams, monolithic single-package codebases become difficult to maintain, leading to slow build times, accidental tight coupling, and merge conflicts. App Modularization solves this by splitting a codebase into decoupled, reusable Dart packages.
1. Feature-First vs Package-Based Monorepo Architecture
[ Monolithic Codebase ] [ Package-Based Monorepo Architecture ]
ββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββββββββββ
β lib/ β β apps/main_app (Entrypoint & Wiring) β
β βββ features/auth/ β ββββββββββββββββββββββ¬βββββββββββββββββββββ
β βββ features/pay/ β β
β βββ core/ β βββββββββββββββββββββ΄ββββββββββββββββββββ
ββββββββββββββββββββββββββ βΌ βΌ
(Easy to cross-import) βββββββββββββββββββ βββββββββββββββββββ
β feature_auth β ββ(cannot import)βββΊβ feature_payment β
ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ
β β
βββββββββββββββββββββ¬ββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββ
β core_network / core_ui β
βββββββββββββββββββββββββββFeature-First Folder Structure (Single Package)
Organizes files by business domains inside a single lib/ folder:
lib/src/features/authentication/ (domain, data, presentation).
- Pros: Easy to start, low setup overhead.
- Cons: Does NOT enforce hard import boundaries. Developers can accidentally import internal files from un-related features.
Package-Based Monorepo Architecture (Multi-Package)
Splits features into isolated local Dart packages inside a monorepo (packages/feature_auth/pubspec.yaml).
- Pros: Compiler-enforced isolation.
feature_authcannot importfeature_paymentunless explicitly declared inpubspec.yaml. Faster incremental compilation. - Cons: Requires monorepo management tools (Melos).
2. Preventing Circular Dependencies & Barrel Files
In a package-based architecture, circular dependencies (Package A -> Package B -> Package A) fail at compile-time.
Strategies to Prevent Tight Coupling
- Decoupled Navigation: Use declarative routing (e.g.
go_router) with string/enum paths instead of importing target screen widgets directly across feature modules. - Core Contracts (
core_foundation): Move shared data interfaces, event buses, and deep links into a sharedcorepackage that feature modules depend on. - Strict Barrel Exports: Expose ONLY public API contracts via
src/barrel files (auth.dart). Keep implementation details private underlib/src/.
// lib/feature_auth.dart (Public API Barrel File)
export 'src/presentation/auth_screen.dart';
export 'src/domain/auth_user.dart';
// Internal data sources under src/ are NOT exported!3. Monorepo Management with Melos
Melos is a CLI tool for managing multi-package Dart/Flutter repositories using pub workspaces.
Key Capabilities
- Simultaneous Bootstrapping:
melos bootstraplinks local packages viapubspec.yamlwithout needing pub.dev publishing. - Cross-Package Script Execution:
melos exec -- "flutter test"runs unit tests across 20+ packages concurrently. - Conventional Commits & Automated Versioning: Automatically generates CHANGELOG.md and bumps package semantic versions.
# melos.yaml
name: my_flutter_monorepo
packages:
- apps/*
- packages/*
- core/*
scripts:
test:
run: melos exec --dir-exists="test" -- "flutter test"
description: Run unit tests across all modular packages.4. Trade-offs & Production Considerations
- CI/CD Build Times: Modular packages drastically improve incremental compilation and CI build times by running tests and static analysis in parallel exclusively on modified packages.
- Initial Setup Overhead: Monorepos require strict package boundaries, dependency management, and Melos configuration skills. Avoid over-modularizing premature codebases with fewer than 3 developers.