Dart to JavaScript Compilation
Dart can compile to JavaScript using dart compile js (also known as dart2js). This guide explains how it works and how to use it with dart_node.
How It Works
The Dart compiler performs several transformations:
- Type checking - Verifies your code is type-safe
- Tree shaking - Removes unused code
- Minification - Reduces output size (in production mode)
- Optimization - Inlines functions, constant folding, etc.
The result is efficient JavaScript that runs anywhere JS runs.
Basic Usage
# Compile a Dart file to JavaScript
dart compile js lib/main.dart -o build/main.js
# With optimizations for production
dart compile js lib/main.dart -o build/main.js -O2
Optimization Levels
| Level | Description | Use Case |
|---|---|---|
-O0 |
No optimization | Debugging |
-O1 |
Basic optimization | Development |
-O2 |
Full optimization (default) | Production |
-O3 |
Aggressive optimization | Maximum performance |
-O4 |
Most aggressive | When size/speed is critical |
Node.js Compatibility
Standard dart2js output is designed for browsers. For Node.js, you need to add a preamble. The node_preamble package handles this:
// In your build script
import 'package:node_preamble/preamble.dart' as preamble;
void main() {
final dartOutput = File('build/app.dart.js').readAsStringSync();
final nodeCompatible = '${preamble.getPreamble()}\n$dartOutput';
File('build/app.js').writeAsStringSync(nodeCompatible);
}
Or use our build tool (recommended):
dart run tools/build/build.dart my_app
Output Structure
A compiled Dart application produces:
build/
├── main.js # Main JavaScript output
├── main.js.deps # Dependency information
└── main.js.map # Source maps (for debugging)
Source Maps
Source maps let you debug Dart code in JavaScript environments:
# Generate with source maps (default)
dart compile js lib/main.dart -o build/main.js
# Disable source maps
dart compile js lib/main.dart -o build/main.js --no-source-maps
In Node.js, enable source map support:
node --enable-source-maps build/main.js
Deferred Loading
Split your app into multiple chunks for faster initial load:
import 'heavy_feature.dart' deferred as heavy;
Future<void> loadFeature() async {
await heavy.loadLibrary();
heavy.runFeature();
}
This creates separate .part.js files loaded on demand.
Interacting with JavaScript
Dart can call JavaScript and vice versa. See the JS Interop guide for details.
Common Issues
"Cannot find dart:html"
This happens when using browser-only libraries in Node.js. Solution: use dart:js_interop instead of dart:html.
Large Output Size
The output can be large for small apps because Dart includes its runtime. For production:
dart compile js lib/main.dart -o build/main.js -O4
Async/Await Issues
Dart's async/await compiles to JavaScript promises. Ensure your Node.js version supports them (Node 8+).
Build Script Example
Here's a complete build script for a dart_node project:
// tools/build.dart
import 'dart:io';
import 'package:node_preamble/preamble.dart' as preamble;
Future<void> main(List<String> args) async {
final target = args.isNotEmpty ? args[0] : 'server';
final inputFile = 'lib/$target.dart';
final outputFile = 'build/$target.js';
print('Compiling $inputFile...');
// Run dart compile js
final result = await Process.run('dart', [
'compile', 'js',
inputFile,
'-o', '$outputFile.tmp',
'-O2',
]);
if (result.exitCode != 0) {
print('Compilation failed:');
print(result.stderr);
exit(1);
}
// Add Node.js preamble
final dartOutput = File('$outputFile.tmp').readAsStringSync();
final nodeOutput = '${preamble.getPreamble()}\n$dartOutput';
File(outputFile).writeAsStringSync(nodeOutput);
// Cleanup
File('$outputFile.tmp').deleteSync();
print('Output: $outputFile');
print('Run with: node $outputFile');
}
Performance Tips
-
Use
-O2or higher for production - Significant size and speed improvements -
Enable tree shaking - Ensure you're not importing unused code
-
Avoid
dynamic- The compiler can't optimize dynamic calls -
Prefer
const- Constant values are evaluated at compile time -
Profile your output - Check the
.js.infofile for size breakdown:
dart compile js lib/main.dart -o build/main.js --dump-info
Next Steps
- JS Interop - Call JavaScript from Dart
- dart_node_core - Core utilities for Node.js
- dart_node_express - Build Express servers