skip to content

Packages & Pub

How Dart code splits into libraries, declares dependencies in pubspec.yaml, resolves to a lockfile with pub, ships to pub.dev and forms workspaces. Interviewers probe constraints and conflicts.

part ofDartoverview, primer and where to startread it →
on this pageshow

explore

questions

25

In a Flutter app's pubspec.yaml, which versions do `http: ^1.2.0` and `http: ^0.13.6` allow, and how is each written without a caret?

level: juniorimportance: must knowfreq 55%

answer

  1. caret means compatible range
  2. 1.x: up to next major
  3. 0.x: up to next minor
  4. quote anything containing >
  5. no constraint means any

basics

~20 s

In pub, ^1.2.0 allows >=1.2.0 <2.0.0, up to the next major, while ^0.13.6 allows >=0.13.6 <0.14.0, up to the next minor, because below 1.0 a minor bump may break. Written longhand, the range must be quoted.

solid answer

~40 s

Pub reads `^version` as "every version guaranteed compatible with this one": for **1.0 and later** that is up to the next **major** (`^1.2.0` = `'>=1.2.0 <2.0.0'`), and **below 1.0** up to the next **minor** (`^0.13.6` = `'>=0.13.6 <0.14.0'`), because a 0.x minor release may break. So an app on `http: ^1.2.0` picks up 1.x fixes and features but never 2.0 without a pubspec edit. The traditional syntax uses comparison operators and must be **quoted** whenever it contains `>`, or YAML misreads it. An exact pin like `1.2.3` or `any` is discouraged; dart.dev recommends caret syntax, and a missing constraint on a hosted dependency means `any`.

code

yaml · 9 lines
yaml
dependencies:
  # 1.2.0 <= v < 2.0.0 : any 1.x from 1.2.0
  http: ^1.2.0
  # 5.4.0 <= v < 6.0.0
  dio: ^5.4.0
  # 0.3.1 <= v < 0.4.0 : pre-1.0 stops at next minor
  some_beta_sdk: ^0.3.1
  # Traditional syntax: quoted because it contains '>'
  intl: '>=0.19.0 <0.21.0'

go deeper

for a junior

Know both caret rules: 1.x and later runs to the next major, 0.x runs to the next minor, and quote ranges containing >.

for a middle

Explain why the 0.x rule differs, and how constraints and the lockfile split the roles of allowing and pinning versions.

for a senior

Choose lower bounds from the APIs you actually use, keep package constraints wide, and treat each major bump as a reviewed change.

for a principal

Set constraint policy across many apps and packages, balancing automatic fixes against the risk of wide ranges.

## What a constraint says Every entry in `dependencies` pairs a package with a **version constraint**: the set of versions your code is willing to use. Pub's solver then picks one version per package that satisfies every constraint in the graph. Pub follows semantic versioning, so the constraint is really a statement about which releases you expect to be compatible. Pub supports two syntaxes that describe the same kind of range: **caret syntax** (the recommended one, allowed in SDK constraints since Dart 2.19) and the **traditional syntax** of comparison operators. ## Caret syntax in pub `^version` means the range of all versions guaranteed to be **backwards compatible** with the given version, up to the next one allowed to break: | Constraint | Allows | Traditional form | |---|---|---| | `^1.2.0` | 1.2.0 up to, not including, 2.0.0 | `'>=1.2.0 <2.0.0'` | | `^1.3.0` | 1.3.0 up to, not including, 2.0.0 | `'>=1.3.0 <2.0.0'` | | `^0.13.6` | 0.13.6 up to, not including, 0.14.0 | `'>=0.13.6 <0.14.0'` | | `^0.1.2` | 0.1.2 up to, not including, 0.2.0 | `'>=0.1.2 <0.2.0'` | The split at 1.0 is the thing interviewers probe. For a **1.0-or-later** package, only a major bump may break, so the caret runs to the next major. For a **pre-1.0** package, a minor bump is allowed to break, so the caret stops at the next minor. Moving from `http: ^0.13.6` to the 1.x line was therefore always a pubspec edit, never something `dart pub upgrade` did on its own. ## Traditional syntax and YAML quoting The traditional syntax combines `>=`, `>`, `<=` and `<` bounds, plus an exact version or `any`. dart.dev's guidance on each: - `>=1.2.3` as a lower bound: yes; - `<2.0.0` as an upper bound where you know the first breaking version: yes; - an exact version such as `1.2.3`: no, because it limits every app that uses your package; - `any`: no, it is an empty constraint, and a hosted dependency written without a constraint is treated as `any`. One mechanical rule causes real bugs: if a constraint contains `>`, **quote the whole string**, as in `'>=1.2.3 <2.0.0'`. Unquoted, YAML can read the `>` as syntax rather than as part of the value. ## Constraining an HTTP client to a safe major A typical team rule is "accept fixes and features automatically, never a breaking release". With a 1.x or later package that is simply a caret on the lowest version whose features you use: 1. Check which version introduced the APIs you call. 2. Write `http: ^1.x.0` (or `dio: ^5.x.0`) with that version as the lower bound. 3. Let `dart pub upgrade` move within the major; the lockfile records what was picked. 4. Treat the next major as a deliberate change: edit the constraint, read the changelog, re-test. For a **0.x** dependency the same rule means a caret that stops at the next minor, so expect more frequent pubspec edits. ## Why not pin exact versions In an app, exact pins mostly duplicate what `pubspec.lock` already guarantees, and they block security fixes. In a package, they are worse: every consumer inherits the pin and is far more likely to hit a solving conflict. Caret constraints plus a committed lockfile for apps give both reproducibility and upgrades.

  • In pub, why does `^0.13.6` stop at 0.14.0 instead of 1.0.0?
    Pub's caret covers versions guaranteed compatible with the given one. Below 1.0, semantic versioning lets a minor release break the API, so the next minor is the first possibly breaking version and the caret ends just before it.
  • In a Dart pubspec, what goes wrong with an unquoted `>=1.2.3 <2.0.0` constraint?
    The `>` character is significant in YAML, so an unquoted value may not be read as the intended string, and pub gets something other than the range you meant. dart.dev says to quote the whole constraint, or use the equivalent caret `^1.2.3`.

saying these in an interview costs you the question

  • ^0.13.6 allows everything up to 1.0.0
  • ^1.2.0 lets pub upgrade jump to 2.0.0
  • Pinning exact versions is the safe default for packages
  • Traditional ranges never need quoting in pubspec.yaml
  • Omitting the version pins to the latest release
open as a page

In a Flutter or Dart pubspec.yaml, what decides whether a package belongs under `dependencies` or `dev_dependencies`, and what changes for your package's consumers?

level: juniorimportance: must knowfreq 60%

basics

~20 s

Anything imported from lib/ or bin/ must be a regular dependency; packages used only by tests, examples or tooling go in dev_dependencies. Pub installs your own dev dependencies but ignores the dev dependencies of every package you depend on.

open as a page

In Dart, what does a leading underscore make private, and why can another class in the same file read a `_field` it does not own?

level: middleimportance: must knowfreq 60%

basics

~20 s

A leading underscore makes a name private to its library, meaning the file plus any part files, not to its class. Every declaration in that library can use it, while other libraries, including your own tests, cannot.

open as a page

In Dart's pub tool, what is the difference between `dart pub get` and `dart pub upgrade`, and how does each treat pubspec.lock?

level: middleimportance: must knowfreq 60%

basics

~20 s

dart pub get keeps the versions already recorded in pubspec.lock and resolves only what is new or missing; dart pub upgrade ignores the lockfile and picks the newest versions the pubspec constraints allow, then writes a new lockfile.

open as a page

In a published Dart 3 package, why is adding a method to a plain public class, or a subtype to a sealed class, a breaking change?

level: seniorimportance: must knowfreq 40%

basics

~20 s

Dart classes are implicit interfaces, so a new member breaks users who implements the class, and a new sealed subtype or enum value breaks their exhaustive switches. Marking a class final stops outside subtyping, so its members can grow in minor releases.

open as a page

In Dart, when two imported libraries both declare a class named `Element`, how do `import ... as`, `show` and `hide` resolve the clash?

level: juniorimportance: should knowfreq 45%

basics

~20 s

Bind one library to a prefix with as, so its names are reached as lib2.Element, or narrow an import with show (only the listed names) or hide (everything except the listed names). Unresolved clashes are errors only where the name is used.

open as a page

In a Dart pubspec.yaml, what does `publish_to: none` do, and why should an app or private package set it?

level: juniorimportance: should knowfreq 40%

basics

~20 s

publish_to: none makes dart pub publish refuse to upload the package anywhere. Without the key pub publishes to pub.dev, where versions essentially cannot be deleted, so apps and private packages set it to block an accidental, permanent upload.

open as a page

In a Dart pub workspace, what do the root pubspec's `workspace` list and each member's `resolution: workspace` do together?

level: juniorimportance: should knowfreq 22%

basics

~20 s

The root pubspec.yaml's workspace list names the member directories, and each member's resolution: workspace opts it in. dart pub get run anywhere then resolves every member together into one pubspec.lock and one .dart_tool/package_config.json at the root.

open as a page

In Dart, what do `part` and `part of` do, how does a part differ from a separate library, and when is a `library` directive needed?

level: middleimportance: should knowfreq 30%

basics

~20 s

part splits one library across files: a part file shares its owner's imports, namespace and private names. The part of directive should name its owner by URI string. A library directive is now only needed to attach library-level docs or annotations.

open as a page

With the dart pub tool, what does `dart pub publish --dry-run` check, and how do you control which files the upload contains?

level: middleimportance: should knowfreq 35%

basics

~20 s

dart pub publish --dry-run runs the client-side publishing checks - pubspec, layout, LICENSE, dependencies, analyzer diagnostics, likely secrets - and prints every file it would upload, without uploading. Hidden files and anything matched by .gitignore or .pubignore stay out.

open as a page

On pub.dev, what do a Dart package's pub points and a verified-publisher badge each tell you, and what does neither guarantee?

level: middleimportance: should knowfreq 30%

basics

~20 s

Pub points are pub.dev's automated quality score: file conventions, documentation and an example, platform support, clean static analysis and up-to-date dependencies. A verified-publisher badge proves the publisher controlled a DNS domain. Neither audits the code's correctness, security or maintenance.

open as a page

In a Dart pubspec.yaml, when would you use a hosted, git, path or sdk dependency source, and which ones block publishing to pub.dev?

level: middleimportance: should knowfreq 35%

basics

~20 s

Hosted, the default, fetches versions from pub.dev or another pub server; git pins a repository, branch, tag or commit; path uses a live local directory; sdk: flutter takes a package bundled with Flutter. Git and path dependencies cannot be published to pub.dev.

open as a page

In a Dart pubspec.yaml, how does the `environment: sdk:` lower bound select the language version, and what does `// @dart = x.y` change?

level: middleimportance: should knowfreq 35%

basics

~20 s

A package's default language version is the major.minor of its SDK constraint's lower bound, not the SDK you have installed. A // @dart = x.y comment at the top of one library overrides that for that file only.

open as a page

In a Flutter app's CI, what does `dart pub get --enforce-lockfile` guarantee that plain `dart pub get` does not, and should the app commit pubspec.lock?

level: middleimportance: should knowfreq 40%

basics

~10 s

Plain pub get quietly unlocks versions when the pubspec changed, a locked version vanished or the SDK changed, and it rewrites mismatched content hashes. --enforce-lockfile fails instead. Apps commit pubspec.lock; regular packages do not.

open as a page

In Dart's `dart pub outdated` output, what do the Current, Upgradable, Resolvable and Latest columns mean, and which command closes each gap?

level: middleimportance: should knowfreq 30%

basics

~20 s

Current is the locked version, Upgradable the newest your constraints allow, Resolvable the newest that works with everything else if constraints were unbounded, and Latest the newest published. pub upgrade closes Current-to-Upgradable; a constraint edit closes Upgradable-to-Resolvable.

open as a page

In a Dart pub workspace, when `api_client` declares `core: ^2.0.0`, which copy of `core` does it use inside the workspace and after publishing?

level: middleimportance: should knowfreq 28%

basics

~20 s

Inside the workspace api_client resolves to the local packages/core, whatever source the dependency names, as long as that copy's version satisfies ^2.0.0. Once api_client is published, its users get core from pub.dev as an ordinary hosted dependency.

open as a page

When splitting a Dart utilities package into a public API and `lib/src` internals, how do `export ... show` and `lib/src` decide what consumers depend on?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Put implementation in lib/src and a main library at lib/<package>.dart that re-exports chosen names with export ... show. Consumers import the main file; lib/src is private by convention only, so anything exported is the real public API.

open as a page

In a Dart package, why can importing one file as both `package:my_pkg/src/cache.dart` and `../lib/src/cache.dart` break type checks and duplicate a singleton?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Dart identifies a library by its URI, so a package: import and a relative path into lib load the same file twice as two unrelated libraries, with separate classes and separate top-level variables. Type tests fail and singletons exist twice.

open as a page

In a Dart or Flutter pubspec.yaml, what does `dependency_overrides` do, why do overrides in a published package have no effect on its users, and what are the risks?

level: seniorimportance: should knowfreq 30%

basics

~20 s

dependency_overrides forces one version or source of a package for every reference in the graph, ignoring other packages' constraints. Only the root package's overrides are honoured, so a published package's overrides do nothing for users, and forcing an untested version can break at run time.

open as a page

In a Flutter app where `flutter_localizations` needs `intl ^0.20.3` but an older package allows only `intl ^0.19.0`, how do you diagnose and fix the version-solving failure?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Pub needs one intl version for the whole graph, and ^0.20.3 and ^0.19.0 do not overlap. Read the Because chain, confirm with dart pub deps, then upgrade or replace the lagging package; a dependency override is only a temporary, tested last resort.

open as a page

After moving an app and four packages into one Dart pub workspace, `dart pub get` fails on incompatible `http` majors that built fine separately; why, and what are your options?

level: seniorimportance: should knowfreq 25%

basics

~20 s

A workspace resolves every member's dependencies and dev_dependencies together, and a resolution holds one version per package, so ^0.13.0 and ^1.2.0 no longer have a solution. Migrate the lagging member rather than overriding, or keep it outside the workspace.

open as a page

Where does Dart's pub store downloaded packages, and what do `dart pub cache repair`, `gc` and `clean` each do?

level: juniorimportance: nice to knowfreq 15%

basics

~10 s

Pub downloads hosted and git packages into one system-wide cache, ~/.pub-cache by default or PUB_CACHE if set. repair reinstalls cached packages, gc removes packages no current project references, and clean empties the whole cache.

open as a page

In Dart, what does `import ... deferred as` do, and what restrictions apply to a deferred library before and after `loadLibrary()` completes?

level: middleimportance: nice to knowfreq 15%

basics

~20 s

deferred as lets a web app download a library on demand: you await prefix.loadLibrary() before touching its members. Its types cannot appear in the importing file, its constants are not constants there, and the dart tool supports deferral only for web targets.

open as a page

You published `colour_tools` 2.3.0 to pub.dev yesterday, but it declares `collection: ^1.15.0` while calling an API added in a later 1.x; with Dart's pub, do you retract, publish a fix, or discontinue?

level: seniorimportance: nice to knowfreq 15%

basics

~20 s

Publish 2.3.1 with a corrected lower bound and retract 2.3.0 while inside its seven-day window: a fix alone leaves the solver free to pick 2.3.0 wherever 2.3.1 doesn't fit. Discontinuing is for abandoned packages, not one bad version.

open as a page

In a Dart pub workspace, what can a member's `pubspec_overrides.yaml` change, and how do you use it to resolve that member on its own?

level: seniorimportance: nice to knowfreq 12%

basics

~20 s

pubspec_overrides.yaml sits next to a pubspec.yaml and overrides only its dependency_overrides, workspace and resolution keys, usually without being committed. An empty resolution: in it detaches the member, so dart pub get there creates an independent resolution.

open as a page