Expert decisions about startup time, binary size, web targets and generated code depend on how the toolchain works.
Dart has several compilation targets:
- JIT (
dart run, Flutter debug): the VM compiles on the fly, enabling hot reload — new code is injected into the running isolate while its heap is kept. - AOT (
dart compile exe, Flutter release): ahead-of-time compiled machine code with a small runtime, fast startup and no JIT. Reflection viadart:mirrorsis unavailable, which is why Dart relies on code generation (build_runnerwith generators such asjson_serializable). - Web:
dart compile js(dart2js, optimized JavaScript) anddart compile wasm(WasmGC, used by Flutter web's--wasmbuilds).
AOT and web builds perform tree shaking: unreachable code is removed, so binary size depends on what you actually call.
The type system is sound: static types are guaranteed at run time, enforced by the compiler plus a few run-time checks — explicit casts (as), covariant generics, and covariant parameters. Soundness lets AOT compilers trust types to unbox numbers, devirtualize calls and skip null checks.
Memory is managed by a generational garbage collector: a fast scavenger for the young generation (most objects die young) and a concurrent mark-sweep/compact for the old generation. Short-lived allocations are cheap, but in Flutter large allocations per frame still cause GC pauses; reuse buffers in hot paths.
dart:ffi calls C directly from native targets, with NativeFinalizer tying C resource lifetimes to Dart objects.
Example
# Development: JIT with fast edit/run cycles and hot reload in Flutter
dart run bin/main.dart
# Native self-contained executable (AOT, tree-shaken)
dart compile exe bin/main.dart -o build/tool
./build/tool
# Smaller AOT snapshot run by dartaotruntime
dart compile aot-snapshot bin/main.dart
# Web targets
dart compile js -O2 web/main.dart -o build/main.js
dart compile wasm web/main.dart -o build/main.wasm
# Generate code instead of reflection (e.g. json_serializable)
dart run build_runner build --delete-conflicting-outputsRemember
- JIT enables hot reload; AOT gives fast startup and no reflection
- Soundness lets compilers trust static types for optimization
- Generational GC makes short-lived objects cheap, but avoid big per-frame allocations
Watch out for
- Expecting
dart:mirrorsreflection to work in Flutter or AOT builds — use code generation.