Skip to main content
The Dart Dev Compiler (DDC) is a fast, modular compiler that generates modern JavaScript (ES6) for development. It’s optimized for quick incremental compilation and debugging, making it ideal for iterative web development.

Overview

Dartdevc prioritizes developer experience over production optimization:
  • Fast incremental compilation - Rebuild only changed modules
  • Readable output - ES6 JavaScript that resembles the original Dart
  • Source maps - Precise mapping for debugging
  • Modular architecture - Compile libraries independently
Important: DDC is meant to be used by build systems, not directly by developers. Use webdev serve or build_web_compilers instead of invoking dartdevc manually.

How It Works

Modular Compilation

Unlike dart2js which requires the entire application, DDC operates modularly:
╭─────────────╮     ╭──────────────╮     ╭──────────────╮
│ Library A   │────▶│ Summary A    │────▶│ Module A.js  │
╰─────────────╯     ╰──────────────╯     ╰──────────────╯
                           │                      │
╭─────────────╮            │              ╭──────────────╮
│ Library B   │────────────┼─────────────▶│ Module B.js  │
╰─────────────╯            │              ╰──────────────╯

╭─────────────╮     ╭──────────────╮     ╭──────────────╮
│ Library C   │────▶│ Summary C    │────▶│ Module C.js  │
╰─────────────╯     ╰──────────────╯     ╰──────────────╯
Each module:
  1. Takes a set of Dart source files
  2. Receives summaries of dependencies
  3. Performs modular type checking
  4. Generates a single JavaScript module

Representation

DDC maps Dart concepts to ES6 naturally:
Dart classes map to ES6 classes:
// Dart
class Dog {
  String name;
  Dog(this.name);
  void bark() => print('$name says woof!');
}
// Generated JavaScript (simplified)
class Dog {
  constructor(name) {
    this.name = name;
  }
  bark() {
    print(`${this.name} says woof!`);
  }
}

Using DDC

The standard way to use DDC:
# Start development server with hot reload
webdev serve

# Serve on specific port
webdev serve web:8080

# Build development output
webdev build --no-release

With build_web_compilers

For custom build configurations:
# pubspec.yaml
dev_dependencies:
  build_runner: ^2.4.0
  build_web_compilers: ^4.0.0
# Run development build
dart run build_runner serve

# Build once
dart run build_runner build --config debug

Direct Invocation (Advanced)

Not recommended for application development:
# Generate a single module
dart run dev_compiler:dartdevc \
  --modules=amd \
  --summary=summaries/core.sum \
  --out=output.js \
  lib/main.dart

Development Workflow

Fast Incremental Builds

DDC shines during development with minimal rebuild times:
  1. Initial build - Compile all modules (~seconds)
  2. Change a file - Recompile only affected modules (~milliseconds)
  3. Hot reload - Browser updates without full page refresh
# Start dev server
webdev serve

# Edit source files
# Browser automatically reloads changed modules

Debugging

DDC generates high-quality source maps:
// Set breakpoints directly in Dart source
// Browser DevTools show:
//   - Dart variable names
//   - Dart types
//   - Dart source lines
Chrome DevTools:
  1. Open DevTools (F12)
  2. Navigate to Sources tab
  3. Browse to lib/ to see Dart sources
  4. Set breakpoints and inspect variables

Type Checking

DDC performs strict type checking during compilation:
// This will cause a compile error in DDC
void main() {
  String name = 42; // Error: A value of type 'int' can't be assigned
}
Use strong mode for best results:
# analysis_options.yaml
analyzer:
  strong-mode:
    implicit-casts: false
    implicit-dynamic: false

Performance Characteristics

Compilation Speed

First compilation of entire app:
  • Small app (< 1000 LOC): 1-3 seconds
  • Medium app (< 10k LOC): 5-15 seconds
  • Large app (> 10k LOC): 15-60 seconds

Runtime Performance

  • Startup: Slower than dart2js (no tree-shaking)
  • Execution: Comparable to hand-written JavaScript
  • Bundle size: Larger than dart2js (includes unused code)
Use DDC for development, dart2js for production.

Module Systems

DDC supports multiple JavaScript module formats:

AMD (Default)

dartdevc --modules=amd -o output.js input.dart
Use with RequireJS loader.

ES6

dartdevc --modules=es6 -o output.js input.dart
Use with native ES6 module imports.

CommonJS

dartdevc --modules=common -o output.js input.dart
Use with Node.js or Browserify.

Browser Support

DDC generates ES6, requiring modern browsers:
  • Chrome: Latest stable (recommended)
  • Firefox: Latest stable
  • Safari: Latest stable
  • Edge: Chromium-based versions
Note: DDC output is not transpiled to ES5. For older browser support, use dart2js instead.

Comparison with dart2js

Featuredartdevcdart2js
PurposeDevelopmentProduction
Compilation speedVery fastSlow
Incremental buildsYesNo
Output sizeLargeSmall
Tree-shakingNoYes
MinificationNoYes
Source mapsExcellentGood
ReadabilityHighLow (minified)
Runtime performanceGoodExcellent
Browser supportModern onlyAll browsers

Limitations

Stability Warning

The DDC output format is not stable. Do not rely on:
  • Generated JavaScript structure
  • Naming conventions
  • Module boundaries
  • Internal APIs
These may change between Dart SDK versions.

Not for Production

DDC is not recommended for production deployment:
  • No tree-shaking (includes all code)
  • No minification (larger downloads)
  • No advanced optimizations
  • Modern browser requirement
Always use dart2js for production builds.

Not for JavaScript Export

Do not use DDC to create JavaScript libraries:
// ❌ Don't do this
// Expose Dart code as JavaScript API via DDC
Instead:
  • Use dart compile js with explicit JS interop
  • Define stable APIs using dart:js_interop

Configuration

Build Configuration

# build.yaml
targets:
  $default:
    builders:
      build_web_compilers|entrypoint:
        options:
          compiler: dartdevc
          dart2js_args:
            - --no-minify

Analysis Options

# analysis_options.yaml
analyzer:
  strong-mode:
    implicit-casts: false  # Catch type errors early
  errors:
    unused_import: warning
    dead_code: info

Troubleshooting

Slow Incremental Builds

If rebuilds are slow:
  1. Check for circular dependencies
  2. Split large libraries into smaller modules
  3. Use --verbose to identify bottlenecks
webdev serve --verbose

Module Loading Errors

If modules fail to load:
  1. Clear build cache: webdev clean
  2. Rebuild: webdev build --no-release
  3. Check browser console for errors

Type Errors

DDC catches errors dart2js might miss:
// DDC error, dart2js might allow
dynamic x = 'hello';
int y = x; // Error in DDC
Fix by being explicit:
int y = x as int; // Explicit cast

Build docs developers (and LLMs) love