Dart: Dart Package Management
Last updated: 2026-08-26
Dependency management is the project's supply chain — only by managing dependencies well can a project be stable.
1. What You'll Learn
- Complete pubspec.yaml configuration: dependencies / dev_dependencies / dependency_overrides
- Version constraint syntax: ^ / >= / any and Semantic Versioning
- Searching, evaluating, and selecting packages on pub.dev
- Private package hosting and git dependencies
- Bob's Scenario: DataPipeline's dependency configuration
2. A Developer's True Story
(1) Pain Point: Build Failure Due to Dependency Version Conflict
Alice's team used http: ^1.1.0 in their DataPipeline project, but another dependency, api_client, required http: >=0.13.0 <1.0.0. The version constraints were incompatible, causing dart pub get to fail. Worse still, a dependency silently updated a minor version, introducing a breaking change that caused the CI build to fail. The team spent 2 days investigating.
(2) The Solution: Semantic Versioning
Dart uses Semantic Versioning (SemVer) and version constraint syntax to make dependency management predictable. ^1.2.0 means >=1.2.0 <2.0.0, guaranteeing compatibility.
dependencies:
http: ^1.2.0 # Compatible with 1.x, safe minor/patch updates
args: ^2.4.2 # Compatible with 2.x
csv: ^6.0.0 # Compatible with 6.x
(3) The Benefits
- Version constraints make dependency upgrades safe and controllable.
- The pub.dev pub points evaluation system helps select high-quality packages.
dependency_overridestemporarily resolves version conflicts.
3. Complete pubspec.yaml Configuration
(1) Configuration Structure
▶ Example
> **Output:** Run in local DartPad or with `dart run`. All examples in this Dart course are based on Dart 3.x / Flutter 3.x. Results may vary slightly depending on the SDK version.
: Complete pubspec.yaml
name: datapipeline
description: A CLI tool for e-commerce data analytics processing million-level orders
version: 1.0.0
homepage: https://github.com/bob/datapipeline
repository: https://github.com/bob/datapipeline
documentation: https://datapipeline.dev/docs
environment:
sdk: ^3.0.0
dependencies:
# CLI argument parsing
args: ^2.4.2
# HTTP client for API calls
http: ^1.2.0
# CSV file parsing
csv: ^6.0.0
# SQLite database support
sqlite3: ^2.4.0
# Path manipulation utilities
path: ^1.9.0
# Logging framework
logging: ^1.2.0
# YAML configuration parsing
yaml: ^3.1.2
dev_dependencies:
# Testing framework
test: ^1.24.0
# Code generation runner
build_runner: ^2.4.0
# JSON serialization
json_serializable: ^6.7.0
# Lint rules
lints: ^3.0.0
dependency_overrides:
# Temporary: resolve version conflict
# transitive: ^1.0.0
executables:
datapipeline: datapipeline
| Field | Required | Description |
|---|---|---|
name |
Yes | Package name (lowercase + underscores) |
description |
Yes | Package description (60-180 characters) |
version |
No | Semantic version number |
environment |
Yes | SDK version constraints |
dependencies |
No | Runtime dependencies |
dev_dependencies |
No | Development-time dependencies |
dependency_overrides |
No | Force specific version |
4. Version Constraint Syntax
(1) Semantic Versioning
▶ Example
> **Output:** Run in local DartPad or with `dart run`. All examples in this Dart course are based on Dart 3.x / Flutter 3.x. Results may vary slightly depending on the SDK version.
: Version Constraint Syntax
dependencies:
# Caret syntax: ^1.2.3 = >=1.2.3 <2.0.0
package_a: ^1.2.3
# Range syntax
package_b: ">=1.2.3 <2.0.0"
# Minimum version
package_c: ">=1.2.3"
# Any version (dangerous!)
package_d: any
# Exact version
package_e: "1.2.3"
# Git dependency
package_f:
git:
url: https://github.com/user/package_f.git
ref: main
# Path dependency (local development)
package_g:
path: ../package_g
| Syntax | Meaning | Example | Safety |
|---|---|---|---|
^1.2.3 |
>=1.2.3 <2.0.0 |
Most common | High |
>=1.2.3 <2.0.0 |
Range constraint | Precise control | High |
>=1.2.3 |
Minimum version | Higher risk | Medium |
any |
Any version | Not recommended | Low |
1.2.3 |
Exact version | Pinned | High (not flexible) |
(2) Version Resolution Rules
| SemVer Rule | Description | Example |
|---|---|---|
| Major Version | Incompatible API changes | 1.x → 2.x |
| Minor Version | Backward-compatible new features | 1.2 → 1.3 |
- Patch Version | Backward-compatible bug fixes | 1.2.3 → 1.2.4 |
▶ Example
> **Output:** Run in local DartPad or with `dart run`. All examples in this Dart course are based on Dart 3.x / Flutter 3.x. Results may vary slightly depending on the SDK version.
: Version Conflict and Resolution
# Scenario: package_a requires http ^0.13.0, package_b requires http ^1.0.0
# This is a MAJOR version conflict - incompatible!
# Solution 1: Update package_a to a version that supports http ^1.0.0
# Solution 2: Use dependency_overrides (last resort)
dependencies:
http: ^1.2.0
dependency_overrides:
http: ^1.2.0 # Force specific version
5. Evaluating Packages on pub.dev
(1) Evaluation Criteria
| Dimension | Metric | Weight |
|---|---|---|
| Pub Points | Platform support/Documentation/Dependency health | High |
| Likes | Community recognition | Medium |
| Popularity | Usage count | Medium |
| Pub Verified | Publisher verified | High |
| Recent Updates | Maintenance activity | High |
| Platform | Supported platforms | As needed |
▶ Example
> **Output:** Run in local DartPad or with `dart run`. All examples in this Dart course are based on Dart 3.x / Flutter 3.x. Results may vary slightly depending on the SDK version.
: DataPipeline Package Selection
# DataPipeline package selection criteria:
#
# args (pub points: 140/140, likes: 300+)
# - Official Dart team package
# - Stable API, well documented
# - Perfect for CLI argument parsing
#
# http (pub points: 140/140, likes: 1000+)
# - Official Dart team package
# - Standard HTTP client
# - Supports interceptors and streaming
#
# csv (pub points: 130/140, likes: 100+)
# - Community package
# - Handles CSV parsing/writing
# - Active maintenance
#
# json_serializable (pub points: 140/140, likes: 500+)
# - Google package
# - Code generation for JSON
# - Type-safe, AOT compatible
6. Private Packages and Git Dependencies
▶ Example
> **Output:** Run in local DartPad or with `dart run`. All examples in this Dart course are based on Dart 3.x / Flutter 3.x. Results may vary slightly depending on the SDK version.
: Git Dependencies
dependencies:
# Public git repository
custom_client:
git:
url: https://github.com/bob/custom_client.git
ref: v1.0.0 # Tag, branch, or commit
# Private git repository (SSH)
internal_sdk:
git:
url: git@github.com:bob/internal_sdk.git
ref: main
# Specific path within a git repo
shared_utils:
git:
url: https://github.com/bob/monorepo.git
path: packages/shared_utils
ref: stable
▶ Example
> **Output:** Run in local DartPad or with `dart run`. All examples in this Dart course are based on Dart 3.x / Flutter 3.x. Results may vary slightly depending on the SDK version.
: Local Path Dependencies
# For local development and testing
dependencies:
core_lib:
path: ../core_lib
shared_models:
path: ./packages/shared_models
| Dependency Source | Syntax | Applicable Scenario |
|---|---|---|
| pub.dev | package: ^1.0.0 |
Formal dependencies (recommended) |
| Git | git: url: ... |
Unpublished/private packages |
| Local Path | path: ../local |
Development/debugging, monorepo |
7. Bob's Scenario: DataPipeline Dependency Configuration
▶ Example
> **Output:** Run in local DartPad or with `dart run`. All examples in this Dart course are based on Dart 3.x / Flutter 3.x. Results may vary slightly depending on the SDK version.
: Complete Project Dependencies
name: datapipeline
description: E-commerce analytics CLI tool for processing million-level orders
version: 1.0.0
environment:
sdk: ^3.0.0
dependencies:
# CLI framework
args: ^2.4.2
# Console output formatting
cli_util: ^0.4.1
# HTTP client
http: ^1.2.0
# CSV parsing
csv: ^6.0.0
# JSON serialization
json_annotation: ^4.8.0
# Path utilities
path: ^1.9.0
# Logging
logging: ^1.2.0
# YAML config
yaml: ^3.1.2
dev_dependencies:
# Testing
test: ^1.24.0
# Mocking
mockito: ^5.4.0
# Code generation
build_runner: ^2.4.0
json_serializable: ^6.7.0
# Linting
lints: ^3.0.0
# Coverage
coverage: ^1.6.0
8. Complete Example: DataPipeline Dependency Management
// ============================================
// DataPipeline Dependency Management Demo
// Shows how to use key dependencies
// ============================================
import 'package:args/args.dart';
import 'package:path/path.dart' as p;
const String version = '1.0.0';
class DataPipelineCli {
final ArgParser parser;
DataPipelineCli()
: parser = ArgParser()
..addFlag('version', abbr: 'v', negatable: false, help: 'Show version')
..addFlag('help', abbr: 'h', negatable: false, help: 'Show help')
..addOption('input', abbr: 'i', help: 'Input data source')
..addOption('output', abbr: 'o', defaultsTo: 'report.json', help: 'Output path')
..addOption('format', allowed: ['json', 'csv', 'html'], defaultsTo: 'json')
..addFlag('verbose', abbr: 'V', help: 'Verbose logging')
..addOption('batch-size', defaultsTo: '10000', help: 'Records per batch');
Future<void> run(List<String> arguments) async {
try {
final results = parser.parse(arguments);
if (results['help'] as bool) {
_printHelp();
return;
}
if (results['version'] as bool) {
print('DataPipeline v$version');
return;
}
final input = results['input'] as String?;
final output = results['output'] as String;
final format = results['format'] as String;
final verbose = results['verbose'] as bool;
final batchSize = int.parse(results['batch-size'] as String);
if (input == null) {
print('Error: --input is required');
_printHelp();
return;
}
// Use path package for cross-platform paths
final inputPath = p.normalize(input);
final outputPath = p.normalize(output);
final ext = p.extension(inputPath);
print('=== DataPipeline v$version ===');
if (verbose) {
print('Input: $inputPath (${ext.isEmpty ? "unknown" : ext})');
print('Output: $outputPath');
print('Format: $format');
print('Batch size: $batchSize records');
print('SDK: ${_getSdkInfo()}');
}
print('Processing: $inputPath → $outputPath ($format)');
} on FormatException catch (e) {
print('Argument error: ${e.message}');
print(parser.usage);
}
}
void _printHelp() {
print('DataPipeline - E-commerce analytics CLI tool');
print('');
print('Usage: datapipeline [options]');
print(parser.usage);
}
String _getSdkInfo() {
// In real project, use dart:io Platform
return 'Dart 3.x';
}
}
void main(List<String> arguments) async {
final cli = DataPipelineCli();
await cli.run(arguments);
}
> **Output:** Run in local DartPad or with `dart run`. All examples in this Dart course are based on Dart 3.x / Flutter 3.x. Results may vary slightly depending on the SDK version.
Output (
dart run bin/main.dart -i orders.csv -o report.json -V):
=== DataPipeline v1.0.0 ===
Input: orders.csv (.csv)
Output: report.json
Format: json
Batch size: 10000 records
SDK: Dart 3.x
Processing: orders.csv → report.json (json)
❓ FAQ
Q: What is the difference between
dependenciesanddev_dependencies? A:dependenciesare packages needed at runtime;dev_dependenciesare only needed during development (testing, code generation, linting). When publishing a package,dev_dependenciesare not passed on to users.
Q: What is the difference between
^and>=? A:^1.2.0is equivalent to>=1.2.0 <2.0.0, limiting updates within a major version.>=1.2.0has no upper bound.^is safer and recommended.
Q: What is the difference between
dart pub upgradeanddart pub get? A:dart pub getfetches dependencies within the constraints of pubspec.yaml.dart pub upgradeattempts to upgrade to the latest versions within those constraints.
Q: Should pubspec.lock be committed to version control? A: For application projects (CLI, Flutter App), yes, to ensure the team uses identical versions. For library projects (packages), no, to allow users to get the latest compatible version.
Q: How to choose a package on pub.dev? A: Check pub points (≥130 is good), likes, recent update time, and if the publisher is verified. Prefer official Dart/Google packages.
Q: When should I use
dependency_overrides? A: Only temporarily when conflicts cannot be resolved through normal version constraints. Long-term use masks underlying problems. Remove it as soon as the issue is resolved.
Q: Are git dependencies safe for production? A: Not recommended. Git dependencies have no version guarantee, and
refcan be force-pushed. For formal releases, use versioned packages from pub.dev.
📖 Summary
- pubspec.yaml is the project's configuration center: manages dependencies, versions, and metadata.
- Using the
^syntax for version constraints is safest, allowing automatic upgrades within a major version. - pub.dev's pub points evaluation system helps select high-quality packages.
- Git dependencies are for unpublished/private packages, while path dependencies are for local development.
dependenciesvsdev_dependenciesseparates runtime from development-time dependencies.
📝 Exercises
- Basic (Difficulty ⭐): Create a project using
dart create, add theargsandpathdependencies, rundart pub get, and inspect the content of the pubspec.lock file. - Intermediate (Difficulty ⭐⭐): Search for the
httppackage on pub.dev, record its pub points, likes, latest version, and supported platforms. Write a package selection evaluation report. - Challenge (Difficulty ⭐⭐⭐): Create a pubspec.yaml file that includes a git dependency and a path dependency, simulating a monorepo development scenario. Use
dependency_overridesto resolve a hypothetical version conflict.