Build Prepare
The build-prepare command swaps debug and release dependencies at build time. It performs two passes:
- pubspec.yaml swap — replaces debug package names with noop package names (or vice versa) in all
pubspec.yamlfiles undertarget_paths - Dart import rewrite — replaces
package:import URIs in.dartfiles underlib/andtest/inside eachtarget_path, so host code stays valid after the package name swap
Usage
# Swap to debug dependencies for development
dart run monorepo_toolkit build-prepare debug
# Swap to release (noop) dependencies for production builds
dart run monorepo_toolkit build-prepare release
# Use a custom config path
dart run monorepo_toolkit build-prepare release --config path/to/config.yamlConfiguration
Create a build_prepare.yaml at the workspace root:
build_prepare:
mappings:
- debug: monitoring_impl
release: monitoring_noop
- debug: app_launch_tracker_impl
release: app_launch_tracker_noop
target_paths:
- apps/template_appConfiguration fields
| Field | Required | Description |
|---|---|---|
mappings[].debug | Yes | The debug/development package name (e.g., monitoring_impl) |
mappings[].release | Yes | The release/noop package name (e.g., monitoring_noop) |
target_paths | No | Directories to scan. If empty, scans all workspace packages (pubspec swap only; no import rewrite) |
How it works
Pass 1 — pubspec.yaml swap
Every occurrence of the debug package name is replaced with the release package name in pubspec.yaml (and vice versa for debug mode). This covers both the dependency key and the path: reference.
Debug mode (pubspec.yaml after build-prepare debug):
dependencies:
app_launch_tracker_impl:
path: ../../infrastructure/app_launch_tracker_implRelease mode (pubspec.yaml after build-prepare release):
dependencies:
app_launch_tracker_noop:
path: ../../infrastructure/app_launch_tracker_noopPass 2 — Dart import rewrite
After the pubspec swap, build-prepare walks every .dart file under lib/ and test/ inside each target_path and rewrites two patterns:
package:<debug_pkg>/→package:<release_pkg>/(all import paths)/<debug_pkg>.dart→/<release_pkg>.dart(barrel file references)
Example — an import in apps/template_app/lib/di/injector.dart:
// Before (debug):
import 'package:app_launch_tracker_impl/app_launch_tracker_impl.dart';
// After build-prepare release:
import 'package:app_launch_tracker_noop/app_launch_tracker_noop.dart';The rewrite is reversible: build-prepare debug swaps the names back, restoring the original imports exactly.
Why import rewrite is required
build_prepare never rewrites class names — only import paths. This means both the debug impl and the release noop must export a class of the same name. When app_launch_tracker_impl is swapped out for app_launch_tracker_noop, AppLaunchTracker is still the class name in both packages. The only thing that changes is the import path, which build-prepare handles automatically.
This is the unified-class-name Impl/Noop pattern — see the architecture guide for when to use it.
Melos shortcuts
melos run build-prepare:debug # Swap to debug dependencies
melos run build-prepare:release # Swap to release (noop) dependenciesFastlane integration
The template's Fastfile calls build-prepare automatically:
before_all do
sh("dart run monorepo_toolkit build-prepare release")
end
after_all do
sh("dart run monorepo_toolkit build-prepare debug")
endAlways restore debug dependencies after the build, even if the build fails.
CI integration
steps:
- name: Prepare release deps
run: dart run monorepo_toolkit build-prepare release
- name: Build release
run: flutter build appbundle --flavor production
- name: Restore debug deps
if: always()
run: dart run monorepo_toolkit build-prepare debugWhen to use this
Use build-prepare for packages that:
- Have a debug implementation with vendor SDKs or profiling overhead
- Should be completely absent from release builds (not just disabled at runtime)
- Follow the Impl/Noop pattern with unified class names (no
_apicontract needed)
The monitoring_impl / monitoring_noop pair is the canonical API/Impl/Noop example (both implement AppMonitoring from monitoring_api). The app_launch_tracker_impl / app_launch_tracker_noop pair is the canonical Impl/Noop without _api example — both export class AppLaunchTracker with identical method signatures, so no shared interface package is needed.