Dart
First appeared 2011 · Lars Bak
Google's language for Flutter — one codebase compiled to native mobile, desktop and web.
Overview
Dart is a client-optimised programming language developed by Google for building fast applications across mobile, web, desktop and server from a single codebase. It is statically typed with sound null safety, and compiles ahead-of-time to native machine code for production and just-in-time during development, which is what enables Flutter's sub-second hot reload. Dart's syntax is deliberately familiar to anyone coming from Java, C# or JavaScript, which lowers the cost of adopting it. The language is almost always encountered through Flutter, Google's UI toolkit, where Dart's compilation model and predictable performance characteristics matter more than they would in isolation. Beyond Flutter, Dart compiles to efficient JavaScript for the web and to standalone native executables for command-line tools and servers, giving one language a genuinely wide deployment range.
Key facts
The reference details, without the paragraph.
- First appeared
- 2011
- Designed by
- Lars Bak and Kasper Lund at Google
- Typing
- Static and sound, with full null safety since Dart 2.12
- Execution
- JIT during development for hot reload, AOT to native machine code for release
- Memory model
- Automatic — generational garbage collection tuned for short-lived UI objects
- Package manager
- pub, backed by pub.dev
- File extensions
- .dart
- Current version
- Dart 3.x, released alongside each Flutter version
- Compile targets
- ARM and x64 native, JavaScript, WebAssembly
- Licence
- BSD 3-clause
History
How the language got here — the decisions that still shape how you write it.
Dart was announced by Google in 2011 with the ambitious and ultimately abandoned goal of replacing JavaScript in the browser — Chrome was to ship a native Dart VM. That plan was dropped in 2015 when it became clear the web would not accept a second scripting language, and Dart pivoted to compiling to JavaScript instead. The language's real breakthrough came with Flutter, announced in 2017. Flutter needed a language that could be interpreted quickly during development for hot reload and compiled to fast native code for release, with predictable performance and no dependency on platform UI widgets. Dart, controlled entirely by Google and designed by Lars Bak — who had previously built the V8 JavaScript engine and the HotSpot JVM — fitted precisely. Dart 2 in 2018 made the type system sound, and Dart 3 in 2023 added pattern matching, records and sealed classes, bringing it closer to modern typed languages. Today Dart's fortunes are essentially tied to Flutter's, and Flutter has become one of the most widely used cross-platform UI frameworks in the industry.
- 2011
Announced as a JavaScript replacement
Google unveils Dart with the stated goal of shipping a native Dart VM in Chrome. The web ecosystem does not take to the idea of a second scripting language.
- 2015
The browser VM is abandoned
Google drops the plan to embed Dart in Chrome and commits to compiling to JavaScript instead. For a period the language looks like it may not find a purpose.
- 2017
Flutter changes everything
Flutter is announced and Dart becomes its language. The pairing works because Dart supports both fast JIT for hot reload and AOT compilation for release performance — few languages do both well.
- 2018
Dart 2 makes the type system sound
Optional typing is removed in favour of a sound static type system, so a variable's declared type is guaranteed at runtime.
- 2021
Sound null safety
Nullable and non-nullable types become distinct, eliminating null dereference errors at compile time rather than runtime.
- 2023
Dart 3 — records, patterns and sealed classes
Pattern matching, destructuring, records and sealed class hierarchies bring Dart in line with modern typed languages, and make exhaustive state handling checkable.
- 2024–2025
WebAssembly and continued Flutter growth
Dart gains a WebAssembly compilation target, improving web performance substantially, while Flutter consolidates its position in cross-platform development.
What it is good at
The reasons teams pick it, stated concretely.
Hot reload genuinely changes the feedback loop
Sub-second reload with state preserved means you adjust a widget and see the result before you have looked away. This is the single feature Flutter developers cite most, and it depends on Dart's JIT.
Sound null safety, not best-effort
The compiler guarantees a non-nullable variable is never null, including across generics and collections. Unlike gradual approaches, there is no unchecked corner where null slips through.
One codebase, six targets
iOS, Android, web, Windows, macOS and Linux from the same source, with genuinely native compiled output rather than a web view. For a small team this is a large multiplier.
Deliberately unremarkable syntax
Anyone from Java, C#, Swift, Kotlin or TypeScript can read Dart within an hour. That was a design goal, and it makes team adoption far cheaper than a more novel language would be.
Predictable performance for UI
AOT compilation with a garbage collector tuned for many short-lived objects suits the allocation pattern of a widget tree being rebuilt sixty times per second.
Trade-offs
Every language costs you something. Knowing what, before you commit, is the whole point.
Effectively tied to Flutter
Almost nobody chooses Dart for its own sake. Server-side Dart works and the tooling is good, but the ecosystem, jobs and community are all downstream of Flutter's popularity.
A smaller package ecosystem
pub.dev is healthy but far smaller than npm, PyPI or Maven Central. For a niche need you are more likely to write it yourself or wrap a platform API.
Deeply nested widget code
Flutter's composition model produces heavily indented build methods. Dart 3's improvements help, but reading an unfamiliar screen still often means tracing eight levels of constructor arguments.
Platform integration still needs platform code
Anything beyond what a plugin already exposes means writing Swift or Kotlin behind a platform channel — so cross-platform does not mean you can avoid knowing the platforms.
Web output is heavy
A Flutter web build ships a rendering engine, so initial download and time to first paint are poor compared with a conventional web application. WebAssembly improves it but does not close the gap.
Code examples
Not syntax tours — the idioms that make code read like the language rather than a translation of another one.
class User {
final String name; // can never be null
final String? email; // explicitly may be null
const User({required this.name, this.email});
}
String describe(User? user) {
// The compiler refuses `user.name` until you handle the null case.
if (user == null) return 'anonymous';
// After the check, `user` is promoted to non-nullable.
final contact = user.email;
if (contact != null && contact.contains('@')) {
return '${user.name} <$contact>';
}
return user.name;
}
// The ?? operator supplies a fallback; ?. short-circuits on null.
final label = user?.email ?? 'no email';// A record — a lightweight tuple with named fields, no class needed.
(String, int) parseVersion(String raw) {
final parts = raw.split('.');
return (parts[0], int.parse(parts[1]));
}
final (major, minor) = parseVersion('3.5'); // destructured
sealed class Result<T> {}
class Success<T> extends Result<T> { final T value; Success(this.value); }
class Failure<T> extends Result<T> { final String message; Failure(this.message); }
String render(Result<List<String>> result) => switch (result) {
Success(value: final items) when items.isEmpty => 'nothing found',
Success(value: final items) => '${items.length} items',
Failure(message: final m) => 'error: $m',
};Future<Dashboard> loadDashboard(String userId) async {
// Both requests start immediately and run concurrently.
final results = await Future.wait([
api.fetchProfile(userId),
api.fetchOrders(userId),
]);
return Dashboard(results[0] as Profile, results[1] as List<Order>);
}
// Streams model a sequence of asynchronous values.
Stream<int> countdown(int from) async* {
for (var i = from; i > 0; i--) {
await Future.delayed(const Duration(seconds: 1));
yield i; // emits without ending the stream
}
}
await for (final tick in countdown(3)) {
print(tick);
}class BookList extends StatelessWidget {
final List<Book> books;
final void Function(Book) onSelect;
const BookList({super.key, required this.books, required this.onSelect});
@override
Widget build(BuildContext context) {
// ListView.builder only builds the rows currently on screen.
return ListView.builder(
itemCount: books.length,
itemBuilder: (context, index) {
final book = books[index];
return ListTile(
key: ValueKey(book.id),
title: Text(book.title),
subtitle: Text(book.author),
onTap: () => onSelect(book),
);
},
);
}
}Common pitfalls
The mistakes that cost everyone an afternoon at least once.
Calling setState for everything
Rebuilding a whole screen to update one label is the most common Flutter performance problem. Push state as far down the tree as possible, or use a state management library with granular rebuilds.
Missing const constructors
A `const` widget is not rebuilt when its parent rebuilds. Omitting it means Flutter reconstructs subtrees unnecessarily — enable the `prefer_const_constructors` lint.
Using BuildContext after an await
The widget may have been disposed while the future was in flight. Guard with `if (!context.mounted) return;` before touching context after any await.
Building lists eagerly
`ListView(children: [...])` constructs every child immediately. Use `ListView.builder` for anything longer than a screenful.
Not disposing controllers
AnimationController, TextEditingController, StreamSubscription and ScrollController all need disposing in `dispose()`, or they leak and keep firing.
Reaching for `late` to silence null errors
`late` defers the null check to runtime, converting a compile error into a LateInitializationError. Use it only when initialisation genuinely cannot happen at construction.
In production
Where it is running at scale, and what it is doing there.
Google
Google Pay, Google Ads and Google Classroom are built with Flutter and Dart.
BMW
The My BMW app, shipped to iOS and Android from one Flutter codebase.
Alibaba
Xianyu, its second-hand marketplace, uses Flutter for a shared mobile interface.
Nubank
Migrated its mobile banking apps to Flutter to unify iOS and Android development.
Learning path
A realistic order to learn things in, with something to build at each step.
- 1
Week 1
The language on its own
Variables and `final`, functions with named and optional parameters, classes and constructors, collections, and null safety. Use DartPad in the browser — no installation needed.
Build this: Write a command-line program that reads a JSON file and prints a summary.
- 2
Week 2
Asynchrony
Futures, `async`/`await`, `Future.wait`, streams and `async*`. Flutter is asynchronous throughout, so this is not optional background knowledge.
Build this: Fetch from a public API, handle errors and loading, and print results as they arrive.
- 3
Weeks 3–5
Flutter fundamentals
Widgets, the difference between stateless and stateful, layout with Row, Column and Flex, navigation, and `ListView.builder`. Learn why `const` constructors matter for rebuild performance.
Build this: Build a two-screen app that lists items from an API and shows a detail view.
- 4
Weeks 6–8
State management and persistence
Pick one approach — Riverpod, Bloc or Provider — and learn it properly rather than sampling all three. Add local storage, and structure the app into layers.
Build this: Add offline caching and a settings screen that persists across restarts.
- 5
Ongoing
Shipping and platform depth
Platform channels for native APIs, Flutter DevTools for profiling rebuilds and jank, testing at widget and integration level, and the release process for each store.
Build this: Profile a janky screen in DevTools and fix the unnecessary rebuilds causing it.
Ecosystem and tooling
The tools you will end up installing whichever project you join.
| Tool | Category | What it does |
|---|---|---|
| Flutter | Framework | The UI toolkit that is the reason to use Dart — mobile, desktop and web from one codebase |
| pub / pub.dev | Packaging | Package manager and registry, built into the Dart SDK |
| Riverpod / Bloc | State | The two dominant state management approaches; Provider is the simpler legacy option |
| Dio | Networking | HTTP client with interceptors, retries and request cancellation |
| freezed + json_serializable | Codegen | Code generation for immutable data classes and JSON mapping |
| Flutter DevTools | Tooling | Widget inspector, rebuild profiler, memory and network views |
| Drift / Isar | Data | Local persistence — Drift is SQLite with typed queries, Isar is a NoSQL alternative |
| very_good_analysis | Code quality | A strict lint rule set, considerably stricter than the defaults |
Dart libraries
Library coverage for Dart is on the way.
The guide above is complete. In the meantime, the catalogues for Python, Java, JavaScript, C and C++ are fully written.
Browse all librariesFrequently asked
Is it worth learning Dart if I am not going to use Flutter?
Honestly, rarely. Dart is a perfectly good general-purpose language with excellent tooling, and server-side Dart works, but its ecosystem, community and job market are overwhelmingly Flutter-driven. Learn it because you want to build cross-platform apps, not on general merit.
Flutter or React Native?
Flutter renders its own widgets with Skia or Impeller, so the UI is pixel-identical across platforms and performance is more predictable — at the cost of not using native controls. React Native uses actual platform components and lets you reuse React knowledge and the npm ecosystem. Flutter usually wins on consistency and animation smoothness; React Native wins if your team already writes React.
Which state management should I use?
Riverpod for new projects — it is compile-time safe, testable and does not depend on BuildContext. Bloc if your team wants strict, event-driven structure and an audit trail of state changes. Provider is simpler and still perfectly serviceable for small apps. Pick one and learn it properly; the common failure is sampling all three.
Is Flutter web production-ready?
It works, but it ships a rendering engine to the browser, so the initial download and time to first paint are poor compared with a normal web app, and text selection, SEO and accessibility are weaker. It suits internal tools and app-like experiences. For a public marketing site or anything SEO-dependent, use a conventional web stack.
What does sound null safety actually mean?
That the compiler can prove a non-nullable variable is never null, so it can remove null checks from the generated code entirely. This is stronger than TypeScript's or Kotlin's approach, where unchecked code at a boundary can still introduce a null the type system believed impossible.
How large is the Dart job market?
Smaller than JavaScript, Python or Java, but growing steadily and almost entirely advertised as Flutter roles rather than Dart roles. It is a strong niche — particularly for agencies and startups shipping to both mobile platforms with a small team.




