What is the difference between dependencies and dev_dependencies in pubspec.yaml?

#flutter#dart#pubspec#dependencies#packages

Answer

Overview

In Flutter/Dart,

text
pubspec.yaml
has two sections for packages:

  • text
    dependencies
    — Packages needed at runtime (included in the final app build)
  • text
    dev_dependencies
    — Packages needed only during development (NOT included in production)

dependencies

Packages listed under

text
dependencies
are compiled into your app and are available at runtime. Your app cannot function without them.

yaml
# pubspec.yaml
dependencies:
  flutter:
    sdk: flutter

  # State management
  provider: ^6.1.2
  flutter_bloc: ^8.1.6

  # Networking
  http: ^1.2.2
  dio: ^5.7.0

  # Local storage
  shared_preferences: ^2.3.3
  sqflite: ^2.4.1

  # UI
  cached_network_image: ^3.4.1
  flutter_svg: ^2.0.15

  # Navigation
  go_router: ^14.6.2

  # Firebase
  firebase_core: ^3.8.1
  firebase_auth: ^5.3.4

dev_dependencies

Packages listed under

text
dev_dependencies
are used only during development — for testing, code generation, linting, etc. They are never included in the production app binary.

yaml
# pubspec.yaml
dev_dependencies:
  flutter_test:
    sdk: flutter

  # Testing
  mockito: ^5.4.4
  bloc_test: ^9.1.7
  integration_test:
    sdk: flutter

  # Code generation
  build_runner: ^2.4.13
  json_serializable: ^6.8.0
  freezed: ^2.5.7

  # Linting
  flutter_lints: ^5.0.0
  very_good_analysis: ^6.0.0

  # Launcher icons & splash screen
  flutter_launcher_icons: ^0.14.2
  flutter_native_splash: ^2.4.3

Key Differences

Feature
text
dependencies
text
dev_dependencies
Included in buildYes (production APK/IPA)No
Available at runtimeYesNo
Increases app sizeYesNo
Imported from
text
lib/
YesNo
Imported from
text
test/
YesYes
PurposeApp functionalityTesting, code gen, tooling

The Rule

The official Dart documentation states:

If the dependency is imported from something in your

text
lib/
or
text
bin/
directories, it must be a regular dependency. If it's only imported from
text
test/
or
text
example/
directories, it can and should be a
text
dev_dependency
.

dart
// ✅ In lib/services/api_service.dart — uses regular dependency
import 'package:dio/dio.dart'; // dio must be in dependencies

// ✅ In test/services/api_service_test.dart — uses dev_dependency
import 'package:mockito/mockito.dart'; // mockito can be in dev_dependencies

Common Mistakes

Mistake 1: Putting test packages in dependencies

yaml
# ❌ Wrong — mockito is only used in tests
dependencies:
  mockito: ^5.4.4

# ✅ Correct — keep test packages in dev_dependencies
dev_dependencies:
  mockito: ^5.4.4

Mistake 2: Putting code generation in dependencies

yaml
# ❌ Wrong — build_runner is a dev tool, not runtime
dependencies:
  build_runner: ^2.4.13

# ✅ Correct
dev_dependencies:
  build_runner: ^2.4.13
  json_serializable: ^6.8.0

Mistake 3: Putting runtime packages in dev_dependencies

yaml
# ❌ Wrong — provider is used in lib/ code
dev_dependencies:
  provider: ^6.1.2

# ✅ Correct — provider is needed at runtime
dependencies:
  provider: ^6.1.2

Special Case: Code Generation Packages

Code generation packages have a split setup:

yaml
dependencies:
  json_annotation: ^4.9.0    # Runtime annotations (used in lib/)
  freezed_annotation: ^2.4.4 # Runtime annotations (used in lib/)

dev_dependencies:
  json_serializable: ^6.8.0  # Generator (only runs during dev)
  freezed: ^2.5.7            # Generator (only runs during dev)
  build_runner: ^2.4.13      # Build tool (only runs during dev)

Key Insight: Keeping dev-only packages in

text
dev_dependencies
reduces your production app size and avoids shipping unnecessary code to users. Always ask: "Does my app need this package to run?" If not, it belongs in
text
dev_dependencies
.