This episode covers Dart package management: structuring pubspec.yaml, the difference between public and local packages, the pub.dev ecosystem with versioning, and using dart pub get, dart pub upgrade, and dependency resolution.

No modern application is built from scratch. You'll always use packages written by others, and someday share your own. Episode 8 dissects Dart package management — from structuring pubspec.yaml to correct dependency resolution.
We'll cover how to write a Dart package, the difference between public and local packages, understanding versioning on pub.dev, and using dart pub get, dart pub upgrade, and dart pub outdated correctly.
Clean dependency management is a sign of engineering maturity. Small mistakes here can disrupt teams and production.
Every Dart package is identified by a pubspec.yaml at the root of the project:
name: aplikasi_kasir
description: Aplikasi kasir sederhana untuk belajar.
version: 1.0.0
publish_to: none
environment:
sdk: ^3.5.0
dependencies:
http: ^1.2.0
intl: ^0.19.0
dev_dependencies:
lints: ^4.0.0
test: ^1.25.0The name field must use lowercase letters and underscores. publish_to: none indicates this package won't be published to pub.dev — common for applications. Runtime dependencies go in dependencies, development tooling in dev_dependencies.
A good package puts importable code in lib/:
aplikasi_kasir/
├── bin/aplikasi_kasir.dart
├── lib/kasir.dart
├── test/kasir_test.dart
└── pubspec.yamlWith lib/kasir.dart, other packages can use import 'package:aplikasi_kasir/kasir.dart'. bin/ holds the executable entry point, while test/ stores the tests.
pub.dev is the official Dart package registry. Add a dependency with:
dart pub add httpThe command dart pub add http adds the latest http version to pubspec.yaml and immediately runs dart pub get. It's the fastest way to add a dependency without editing files manually.
For packages not yet published — for example, an internal team package — use a path dependency:
dependencies:
internal_helpers:
path: ../internal_helpersA path: dependency points directly to a local directory, useful for shared development before release to pub.dev.
pub.dev uses Semantic Versioning. Every package has major, minor, and patch versions. Constraints in pubspec.yaml are written with the caret:
dependencies:
dio: ^5.4.0^5.4.0 means version 5.4.0 up to but not including 6.0.0. This allows room for minor and patch updates while protecting against major breaking changes.
Before choosing a package, check on pub.dev: the analysis score, number of likes and points, SDK compatibility, and license. Packages with high scores are generally better maintained and safer to use.
dart pub get downloads dependencies and generates pubspec.lock — a file that pins exact versions for reproducibility:
dart pub getRun dart pub get every time pubspec.yaml changes. Commit the pubspec.lock file for applications so all developers and CI use identical versions.
To update dependencies within constraint limits, use dart pub upgrade. To see available versions, use dart pub outdated:
dart pub outdated
dart pub upgradedart pub outdated shows a table of current versions, latest versions, and versions that violate constraints. dart pub upgrade updates to the latest allowed versions, then re-pins them in pubspec.lock.
Key takeaways:
pubspec.yaml declares the name, SDK, dependencies, and dev_dependencies.dart pub add package_name adds a dependency and runs pub get at the same time.path constraint in pubspec.yaml.^ allows minor and patch updates while protecting against major breaking changes.pubspec.lock pins exact versions for build reproducibility.dart pub outdated checks, dart pub upgrade updates dependencies.In the next episode 9, we'll cover testing and quality — writing unit tests with package:test, grouping tests with group and setup-teardown, using matchers, mocking dependencies, and running all tests with dart test.