Introduction

After running flutter clean, a full rebuild can be extremely slow because it re-downloads all Dart packages from pub.dev, re-resolves Gradle dependencies, and potentially re-downloads CocoaPods. This is especially problematic on slow networks or in CI/CD pipelines. Understanding the caching layers involved and how to preserve them can dramatically reduce build times.

Symptoms

  • flutter pub get takes several minutes after flutter clean
  • Gradle downloads all dependencies from scratch:
  • `
  • Downloading https://services.gradle.org/distributions/gradle-8.4-all.zip
  • ...
  • > Task :app:compileDebugJavaWithJavac
  • `
  • CocoaPods re-installs all native dependencies:
  • `
  • Installing Firebase (10.18.0)
  • Installing FirebaseCore (10.18.0)
  • ...
  • `
  • CI builds taking 10+ minutes instead of 2-3 minutes

Common Causes

  • flutter clean removes .dart_tool/ which triggers full pub get
  • Gradle cache cleared or not shared across builds
  • CI/CD pipeline not caching dependency directories
  • PUB_CACHE environment variable pointing to non-persistent storage
  • Network issues causing repeated download failures

Step-by-Step Fix

  1. 1.Avoid flutter clean unless necessary:
  2. 2.```bash
  3. 3.# Instead of flutter clean, try:
  4. 4.flutter pub get # Usually sufficient after dependency changes

# Only use flutter clean when: # - Generated files are corrupted # - Switching between Flutter SDK major versions # - Experiencing mysterious build errors ```

  1. 1.Use PUB_CACHE for persistent package caching:
  2. 2.```bash
  3. 3.# Set persistent cache location
  4. 4.export PUB_CACHE=$HOME/.pub-cache

# Verify cache exists ls $PUB_CACHE/hosted/pub.dev/ | head -20 ```

  1. 1.Cache Gradle dependencies:
  2. 2.```bash
  3. 3.# Gradle caches to ~/.gradle/caches/ by default
  4. 4.# Ensure this is not cleaned between builds
  5. 5.ls ~/.gradle/caches/modules-2/files-2.1/ | head -10

# For CI/CD, cache these directories: # - ~/.gradle/caches/ # - ~/.gradle/wrapper/ ```

  1. 1.Cache CocoaPods on macOS:
  2. 2.```bash
  3. 3.# CocoaPods caches to ~/.cocoapods/
  4. 4.ls ~/.cocoapods/repos/

# Pre-install pods before CI build cd ios && pod repo-update && cd .. ```

  1. 1.For CI/CD pipelines (GitHub Actions example):
  2. 2.```yaml
  3. 3.- name: Cache Flutter dependencies
  4. 4.uses: actions/cache@v4
  5. 5.with:
  6. 6.path: /opt/hostedtoolcache/flutter
  7. 7.key: flutter-${{ hashFiles('**/pubspec.lock') }}
  • name: Cache Gradle
  • uses: actions/cache@v4
  • with:
  • path: |
  • ~/.gradle/caches
  • ~/.gradle/wrapper
  • key: gradle-${{ hashFiles('/*.gradle*', '/gradle-wrapper.properties') }}
  • name: Cache CocoaPods
  • uses: actions/cache@v4
  • with:
  • path: ~/.cocoapods
  • key: pods-${{ hashFiles('**/Podfile.lock') }}
  • `
  1. 1.Speed up pub get with offline mode when possible:
  2. 2.```bash
  3. 3.# If all packages are already cached:
  4. 4.flutter pub get --offline

# This fails if any package is not in cache, # which tells you exactly what is missing ```

Prevention

  • Only run flutter clean when absolutely necessary
  • Set up CI/CD caching for pub cache, Gradle, and CocoaPods
  • Use --offline flag for local builds when cache is complete
  • Keep pubspec.lock in version control for deterministic resolution
  • Monitor dependency count with flutter pub deps | wc -l
  • Use flutter pub cache clean sparingly - only when cache is corrupted