Dart 3.13 Shrinks Native Binaries and Preps Dynamic Module Loading
Native tree shaking closes a long-standing gap where Dart's aggressive dead-code elimination stopped at the FFI boundary, forcing apps to ship entire native libraries for a handful of used functions. Combined with the dynamic modules experiment, Dart is laying groundwork for both smaller binaries and more flexible deployment models on locked-down platforms like iOS.
Dart 3.13 graduates primary constructors to stable, letting developers declare a class and its fields in a single line. A new `new` keyword inside classes replaces repetitive constructor names, and the formatter now groups imports by source and handles method chains more cleanly. On the documentation side, `dartdoc` can embed real, runnable example code directly from the `example/` directory.
Native tree shaking is the release's most impactful change. By annotating FFI bindings with `@RecordUse` and wiring a link hook into the build, Dart AOT now tells the native linker exactly which C/Rust symbols are reachable. A library exposing 300 APIs where only 20 are called can have the other 280 stripped from the final binary, and entirely unused native libraries can be dropped altogether.
An experimental dynamic modules feature also appears, aimed at letting AOT-compiled Dart code load new Dart modules at runtime. The immediate target is faster internal prototyping on iOS where JIT is unavailable, though the team explicitly states production server-driven UI is not a current priority.
Native tree shaking reconnects two build pipelines that previously operated in isolation, meaning package authors can expose large native APIs without forcing consumers to pay the binary-size cost for unused functions.
The dynamic modules experiment, while framed as a developer-workflow feature, signals that the Dart team is willing to relax the closed-world assumption that has defined AOT compilation, which could eventually enable forms of code push on iOS.
Stabilizing primary constructors alongside a batch of lints and automated refactors shows the team is willing to push syntax modernization aggressively rather than letting new features languish as optional curiosities.
The `dartdoc` example-embedding feature addresses a real maintenance problem: documentation examples drifting out of sync with runnable example code, a pain point in many ecosystems beyond Dart.