Chương 01 · Hello Dart

Hello Dart — lên xe

Cài Dart SDK, chạy file .dart đầu tiên, hiểu CLI toolchain và cấu trúc project tối thiểu. Đây là chương "lên xe" — không có chương này, mọi chương sau đều giả định bạn đã chạy được dart run.

Độ dài: ~750 dòng Bài tập: 5 Quiz: 7 Prerequisites: terminal cơ bản
🎯 Mục tiêu chương
  • Cài được Dart SDK trên macOS (nhắc thêm Linux/Windows).
  • Chạy được file .dart đầu tiên bằng dart run và hiểu vòng đời compile/execute.
  • Biết các lệnh Dart CLI core: run, compile, format, analyze, test, pub.
  • Hiểu cấu trúc một Dart project tối thiểu: pubspec.yaml, lib/, bin/, test/.
  • Sử dụng DartPad cho thí nghiệm nhanh trên trình duyệt.
  • Phân biệt Dart standaloneDart trong Flutter.

1. Dart là gì?

Dart là ngôn ngữ lập trình do Google phát triển, ra mắt tháng 10 năm 2011. Mục tiêu ban đầu: thay thế JavaScript cho ứng dụng web — nhưng kế hoạch đó thất bại. Dart sau đó được tái định vị làm ngôn ngữ chính cho Flutter (2017), và đây là lý do bạn biết đến Dart hôm nay.

Đặc điểm thiết kế của Dart:

  • Client-side optimized — Dart tối ưu cho UI: hot reload nhanh, AOT compile cho production, garbage collector tuned cho UI workload.
  • Sound static type system — type check tại compile-time và analyzer chứng minh được — không như TypeScript "gradual typing".
  • Multi-platform — Dart compile được ra: native binary (ARM, x64), JavaScript (cho web), bytecode chạy trên Flutter engine.
  • Cú pháp quen thuộc — gần với Java/JavaScript/C#, dễ học cho dev đã biết một trong các ngôn ngữ này.
🔀 So sánh nhanh với JS/TS/Kotlin/Swift
Tiêu chíDartTypeScriptKotlinSwift
Type systemSound staticGradual (escape via any)Sound staticSound static
Null safetySound, mặc địnhStrict mode optionalSound, mặc địnhSound, mặc định
RuntimeVM (JIT) / AOT nativeJS engineJVM / NativeNative
Mục đích chínhFlutter UIWeb appAndroid, serveriOS/macOS
Async modelSingle-thread event loop + IsolateEvent loopCoroutineasync/await + actor

Dart vs Flutter — đừng nhầm

Đây là điểm hay bị confuse ở beginner:

  • Dartngôn ngữ. Tự nó chạy được trên terminal qua dart run, viết server (vd với shelf), viết CLI tool, hoặc đơn giản là script.
  • Flutterframework UI viết bằng Dart. Flutter SDK bundle sẵn Dart SDK tương thích, dùng lệnh flutter thay dart.

Sub-pillar này dạy Dart standalone trước — mọi ví dụ trong 8 chương Dart đều chạy bằng dart run, không cần cài Flutter. Sau khi master Dart, qua Flutter sub-pillar (15 chương) sẽ thấy nhẹ nhõm vì syntax đã quen.

2. Cài đặt Dart SDK

3 cách cài Dart SDK trên máy. Recommend cách nào tuỳ vào use case:

Cách 1 — Homebrew (macOS, recommended)

Đơn giản nhất trên macOS:

brew tap dart-lang/dart
brew install dart

Verify:

dart --version
# Output mẫu: Dart SDK version: 3.3.0 (stable) (...) on "macos_arm64"

Linux: dùng apt (Debian/Ubuntu):

sudo apt-get update
sudo apt-get install apt-transport-https
wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo gpg --dearmor -o /usr/share/keyrings/dart.gpg
echo 'deb [signed-by=/usr/share/keyrings/dart.gpg arch=amd64] https://storage.googleapis.com/download.dartlang.org/linux/debian stable main' | sudo tee /etc/apt/sources.list.d/dart_stable.list
sudo apt-get update
sudo apt-get install dart

Windows: tải installer từ dart.dev/get-dart hoặc dùng Chocolatey:

choco install dart-sdk

Cách 2 — Đi kèm Flutter SDK

Nếu sau này sẽ học Flutter, có thể chỉ cần cài Flutter SDK — Dart SDK đi kèm tự động. Lệnh sẽ là flutter pub get, dart run cũng có nhưng dùng Dart trong Flutter SDK.

Nhược điểm: nếu chỉ học Dart, cài thừa hàng GB của Flutter SDK (Android tools, iOS tools).

Cách 3 — Docker

Không muốn cài gì cả? Dùng image official:

docker run --rm -v "$PWD":/app -w /app dart:stable dart run hello.dart

Hữu ích cho CI/CD và máy không tin tưởng (sandbox).

💡 Recommend cho sub-pillar này

Cài qua Homebrew (macOS) hoặc installer (Windows/Linux). Đơn giản, update dễ qua brew upgrade dart. Khi nào học Flutter (sub-pillar 9.2) thì cài thêm Flutter SDK riêng — sẽ override dart command, không sao.

3. DartPad — chạy Dart trên trình duyệt

DartPad (dartpad.dev) là REPL Dart chạy trên trình duyệt. Không cần cài gì — gõ code, bấm Run, ra kết quả. Phù hợp cho:

  • Test một cú pháp mới nhanh (vd thử pattern matching Dart 3 mà chưa muốn update local SDK).
  • Share snippet code với người khác (DartPad có chia sẻ qua URL).
  • Học khi không có máy tính cài Dart sẵn.
📝 Tip: mở dartpad.dev và paste mọi ví dụ trong chương này — chạy được hết. Mở DartPad ↗
⚠️ Hạn chế của DartPad

DartPad là sandbox — không có access I/O thực sự. Không đọc/ghi file disk, không network không restricted-CORS-ok, không gọi process external. Cho học thì đủ, cho project thật thì cần local SDK.

4. Hello World — chạy file Dart đầu tiên

Tạo file hello.dart ở folder bất kỳ:

void main() {
  print('Xin chào, Dart!');
}

Chạy:

dart run hello.dart
# Output: Xin chào, Dart!

Phân tích từng dòng:

  • void main() — entry point của Dart program. Mọi file .dart chạy được phải có hàm main. void là return type — không trả gì.
  • print(...) — built-in function in ra stdout. Khác Java/Python, không cần System.out.println hay print(...) như Python (giống Python format nhưng câu lệnh không phải statement).
  • '...' — string literal, dùng single quote là idiomatic. Double quote cũng được.
  • Mỗi statement kết thúc bằng ; (semicolon bắt buộc, không như Python).
🧠 Khác Python: không có top-level code

Trong Python, viết print('hi') ở top-level file là chạy được. Trong Dart, mọi code phải nằm trong function — và main() là entry. Lý do: Dart compile-first, runtime cần một điểm vào rõ ràng.

Thử thêm: function main có thể nhận command-line arguments:

void main(List<String> args) {
  final name = args.isNotEmpty ? args[0] : 'thế giới';
  print('Xin chào, $name!');
}
dart run hello.dart Việt
# Output: Xin chào, Việt!

dart run hello.dart
# Output: Xin chào, thế giới!

Lưu ý '$name' — đó là string interpolation. Sẽ deep dive ở chương 2. Tạm hiểu: $name được thay bằng giá trị của biến name khi compose string.

5. Dart CLI toolchain

Lệnh dart là Swiss Army knife — gom nhiều subcommand. Bảng các subcommand thường dùng:

LệnhVai tròKhi nào dùng
dart run [file]Chạy file .dart qua JITPhát triển, test nhanh
dart compile exe [file]Compile AOT ra native binaryShip CLI tool standalone
dart compile js [file]Compile ra JavaScriptDart web (hiếm dùng, đa số chuyển Flutter Web)
dart format .Format toàn bộ file .dart trong folderTrước commit, hoặc bật format-on-save
dart analyzeStatic analysis — warning/errorCI, pre-commit check
dart testChạy test trong folder test/TDD, CI
dart pub getResolve + cài dependency từ pubspec.yamlSau khi clone repo hoặc thêm package
dart pub add [package]Thêm package + update pubspec.yamlCài thư viện mới
dart create -t console [name]Tạo project mới từ templateBắt đầu project
dart fix --applyTự fix một số lint warningModernize code cũ

Demo format:

// Trước format — code lủng củng
void main(  ) {var x=1+2;
   print( x);}

Chạy:

dart format hello.dart
// Sau format — chuẩn Dart style
void main() {
  var x = 1 + 2;
  print(x);
}
💡 Format on save

VS Code: bật "editor.formatOnSave": true + "[dart]": { "editor.defaultFormatter": "Dart-Code.dart-code" }. Mỗi lần save tự format — không cần nhớ chạy dart format thủ công.

6. Tạo project chuẩn

Project Dart "real" không chỉ là một file .dart — có structure chuẩn. Tạo nhanh bằng template:

dart create -t console my_app
cd my_app

Structure sinh ra:

my_app/
├── analysis_options.yaml   # Cấu hình analyzer + lint rules
├── bin/
│   └── my_app.dart         # Entry point — main() ở đây
├── lib/
│   └── my_app.dart         # Code reusable, có thể import từ bin/ hoặc package khác
├── test/
│   └── my_app_test.dart    # Unit tests
├── CHANGELOG.md
├── README.md
├── pubspec.lock            # Lock file — phiên bản dependency cụ thể
└── pubspec.yaml            # Manifest project + dependencies

Phân tích từng folder/file:

  • pubspec.yaml — tương đương package.json của Node.js. Liệt kê tên, version, dependency, dev_dependency.
  • bin/ — entry point. File ở đây là "executable" — chạy được bằng dart run.
  • lib/ — code thư viện. Reusable, có thể import từ bin/ hoặc package khác. Quy ước: 1 file = 1 module.
  • test/ — unit test. Pattern: 1 file X.dartlib/ có 1 file X_test.darttest/.
  • analysis_options.yaml — cấu hình analyzer + lint rules. Có thể inherit từ package:lints/recommended.yaml.
  • pubspec.lock — lock file. Cố định version cụ thể của mọi dependency (kể cả transitive). Commit cho app, có thể bỏ cho library.

Chạy template default:

dart run
# Hoặc: dart run bin/my_app.dart
# Output: Hello world: 42!

dart run không có argument tự tìm entry trong bin/. Tiện.

7. pubspec.yaml + package management

Mở pubspec.yaml của project vừa tạo:

name: my_app
description: A sample command-line application.
version: 1.0.0
publish_to: 'none'

environment:
  sdk: ^3.3.0

dependencies:
  args: ^2.4.0

dev_dependencies:
  lints: ^3.0.0
  test: ^1.24.0

Giải thích:

  • name, description, version — meta. name phải lowercase, underscore separator.
  • publish_to: 'none' — đánh dấu không publish lên pub.dev. Bỏ dòng này nếu muốn publish.
  • environment.sdk: ^3.3.0 — yêu cầu Dart SDK ≥ 3.3 và < 4.0 (theo semver caret).
  • dependencies — package runtime. args ^2.4.0 nghĩa là cần version ≥ 2.4 và < 3.0.
  • dev_dependencies — chỉ dùng dev (test, lint). Không ship trong production binary.

Thêm package từ pub.dev

pub.dev là package registry chính thức. Cài package:

dart pub add http
# Tự update pubspec.yaml + chạy pub get
dart pub get
# Resolve deps + tạo .dart_tool/ cache

Sau đó import:

import 'package:http/http.dart' as http;

void main() async {
  final response = await http.get(Uri.parse('https://api.github.com'));
  print(response.body);
}
📘 Note: async/await

Đoạn code trên dùng async/await — sẽ học đầy đủ ở chương 7. Hiện tại tạm hiểu: await đợi response trả về trước khi tiếp tục. main phải gắn async để dùng await bên trong.

.dart_tool/ — đừng commit

Sau pub get, folder .dart_tool/ xuất hiện. Đây là cache analyzer + build artifact. Giống node_modules/ ở JS. Add vào .gitignore:

# .gitignore
.dart_tool/
.packages
build/

8. IDE setup

Recommend 2 lựa chọn, dùng cái nào cũng được:

VS Code (recommended)

Cài 3 extension:

  1. Dart (do Dart Code team Google maintain) — syntax highlight, analyzer integration, debug, hot reload.
  2. Flutter (cùng team) — chỉ cần khi học Flutter sau này. Cài luôn cũng OK.
  3. Awesome Flutter Snippets (optional) — shortcut sinh widget Flutter nhanh.

Settings recommend trong .vscode/settings.json:

{
  "[dart]": {
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "Dart-Code.dart-code",
    "editor.rulers": [80],
    "editor.tabSize": 2,
    "editor.detectIndentation": false
  },
  "dart.lineLength": 80,
  "dart.previewFlutterUiGuides": true
}

IntelliJ IDEA / Android Studio

Cả 2 đều cùng platform JetBrains, cài plugin Dart + Flutter từ marketplace. Lợi thế: debugger mạnh, refactoring tools đầy đủ hơn VS Code. Nhược điểm: nặng máy, RAM ngốn.

Personal recommend: VS Code cho Dart standalone (chương 1-8), Android Studio cho Flutter (đặc biệt với debugger Android).

9. Compile mode — JIT vs AOT

Dart hỗ trợ 2 mode compile:

ModeLệnhTốc độ startTốc độ runtimeUse case
JIT (Just-In-Time)dart runNhanh (no compile)Chậm hơn AOTPhát triển, hot reload
AOT (Ahead-Of-Time)dart compile exeChậm (precompile)Nhanh, nativeProduction, ship binary

Demo:

# JIT — cold start ~1-2s, runtime VM
time dart run hello.dart
# Output: Xin chào, Dart!
# real    0m1.234s

# AOT — compile mất ~5-10s, sau đó cold start ~0.01s
dart compile exe hello.dart -o hello
time ./hello
# Output: Xin chào, Dart!
# real    0m0.012s
🧠 Mental model: Flutter dùng cả 2 mode

Trong Flutter:

  • Debug mode (flutter run) — JIT — cho phép hot reload.
  • Release mode (flutter build apk) — AOT — binary tối ưu cho production.
  • Profile mode — AOT + profile flag — đo performance gần production.

10. Bài tập

Verify môi trường

Cài Dart SDK (chọn 1 trong 3 cách ở section 2). Chạy dart --version và screenshot kết quả. Verify SDK ≥ 3.0 (Dart 3) — không học Dart 2 trong sub-pillar này.

💡 Gợi ý đáp án

Output mong đợi tương tự: Dart SDK version: 3.3.x (stable) (Wed Jan ... 2026 ...) on "macos_arm64". Nếu version < 3.0, update qua brew upgrade dart hoặc tải installer mới.

Greeting với command-line args

Viết file greet.dart nhận tên qua command-line args, in ra "Xin chào, [tên]!". Nếu không có argument, in "Xin chào, người lạ!". Chạy bằng dart run greet.dart Việt.

💡 Gợi ý đáp án
void main(List<String> args) {
  final name = args.isNotEmpty ? args[0] : 'người lạ';
  print('Xin chào, $name!');
}

Mở rộng: thử dart run greet.dart Việt Anh Phương — chỉ in tên đầu vì code lấy args[0]. Nếu muốn join hết: args.join(' ').

Tạo project chuẩn + analyze

Tạo console project mới bằng dart create -t console my_first. Đọc file bin/my_first.dart do Dart sinh ra, giải thích từng dòng. Chạy dart analyze, screenshot output.

💡 Gợi ý đáp án

Template thường có:

import 'package:my_first/my_first.dart' as my_first;

void main(List<String> arguments) {
  print('Hello world: ${my_first.calculate()}!');
}

Giải thích:

  • import 'package:my_first/my_first.dart' — import từ lib/my_first.dart. Prefix package: cho package mode (do pubspec.yaml resolve).
  • as my_first — namespace alias, gọi my_first.calculate() không bị conflict tên.
  • ${my_first.calculate()} — interpolation với expression (cần braces vì có dot access).

dart analyze output kỳ vọng: No issues found!

Add package + đọc lock file

Trong project my_first, thêm package args (dùng cho parsing CLI args): dart pub add args. Mở pubspec.lock, đếm xem có bao nhiêu package được resolve (kể cả transitive deps).

💡 Gợi ý đáp án

pubspec.lock sẽ có nhiều entry hơn bạn nghĩ — vì args kéo theo các transitive deps như collection, meta, etc. Đếm số block name: trong file.

grep -c '^\s*[a-z_]*:$' pubspec.lock
# Hoặc đơn giản: dart pub deps

Lệnh dart pub deps in tree dependency đẹp hơn.

JIT vs AOT — đo thời gian

Compile file greet.dart (từ bài 2) thành executable AOT bằng dart compile exe greet.dart -o greet. So sánh thời gian khởi động (time dart run greet.dart vs time ./greet). Báo cáo chênh lệch.

💡 Gợi ý đáp án

Output kỳ vọng (Mac M1):

$ time dart run greet.dart
Xin chào, người lạ!
real    0m1.123s

$ time ./greet
Xin chào, người lạ!
real    0m0.011s

Chênh ~100x. JIT khởi động chậm vì phải spin up Dart VM + load source + JIT compile. AOT chỉ là native binary chạy thẳng.

Khi nào dùng cái nào? JIT cho phát triển (hot reload). AOT cho ship CLI tool / production server / Flutter release.

11. Quiz

Q1

main() của Dart program có bắt buộc khai báo return type không?

Xem đáp án

Đáp án: Có. void main() hoặc Future<void> main() nếu async. Lý do: Dart strict về type. Nếu viết main() không có return type, analyzer sẽ warning (theo lint rule). Có thể viết được nhưng không nên.

Q2

Khi cài Flutter SDK, có cần cài thêm Dart SDK riêng không?

Xem đáp án

Đáp án: Không. Flutter SDK đi kèm Dart SDK tương thích. Lệnh dart sẽ tìm bin trong Flutter SDK. Nhược điểm: nếu cài cả 2, cần đảm bảo PATH ưu tiên đúng.

Q3

Câu lệnh nào compile Dart ra JavaScript?

Xem đáp án

Đáp án: dart compile js. Dùng cho Dart web pure (hiếm — đa số chuyển Flutter Web qua flutter build web). Có 2 mode: development (fast compile, dễ debug) và production (tree-shaking, minify).

Q4

pubspec.yamlpubspec.lock khác nhau ở điểm nào? Cái nào nên commit vào git?

Xem đáp án

Đáp án: pubspec.yaml là declaration người viết — version constraint dạng range (vd ^2.4.0). pubspec.lock là resolved version cụ thể (vd 2.4.3) do pub get sinh ra, ghi nhớ chính xác mọi dependency + transitive.

Cho app: commit cả 2 — đảm bảo reproducible build (team mới clone cài đúng version). Cho library: commit .yaml, có thể skip .lock — vì user lib resolve theo môi trường họ.

Q5

dart rundart compile exe khác nhau thế nào về performance?

Xem đáp án

Đáp án: dart run dùng JIT (Just-In-Time) — khởi động nhanh (no precompile), runtime chậm hơn AOT.
dart compile exe AOT — compile mất thời gian, sinh ra native binary. Cold start nhanh (~10ms), runtime fast, không cần Dart SDK ở máy chạy.

Trade-off chính: compile time vs runtime time. Production ưu tiên runtime → AOT.

Q6

DartPad có hỗ trợ đọc file từ disk không?

Xem đáp án

Đáp án: Không. DartPad chạy trong sandbox trên trình duyệt — không có access I/O thực sự (không dart:io). Hỗ trợ dart:async, dart:convert, dart:math, và một số package phổ biến đã preload.

Q7

Folder .dart_tool/ có nên commit lên git không? Tại sao?

Xem đáp án

Đáp án: Không. .dart_tool/ là cache analyzer + build artifact — sinh tự động bởi dart pub get, dart analyze, etc. Giống node_modules/ ở Node.js (về vai trò "tự sinh ra, không phải source").

Add vào .gitignore:

.dart_tool/
.packages
build/

12. Tổng kết

Sau chương 1, bạn có:

  • ✅ Dart SDK cài xong, dart --version chạy ra ≥ 3.3.
  • ✅ Hiểu nhanh Dart là gì + vị trí Dart vs Flutter.
  • ✅ Chạy được file .dart đầu tiên bằng dart run.
  • ✅ Biết Dart CLI toolchain: run, compile, format, analyze, test, pub.
  • ✅ Tạo project chuẩn với dart create + hiểu mỗi folder/file vai trò gì.
  • ✅ Cài package từ pub.dev + biết phân biệt pubspec.yaml vs pubspec.lock.
  • ✅ Setup VS Code (hoặc IntelliJ) với extension + settings cho Dart.
  • ✅ Phân biệt JIT vs AOT compile mode.
🧠 Mental model rút ra

Dart là một ngôn ngữ "boring trong cú pháp, sharp trong type system". Cú pháp gần JS/TS/Java — không có gì exotic. Nhưng type system + sound null safety + AOT compile cho phép Flutter chạy mượt trên mobile — đó là raison d'être của Dart.

13. Kết nối tới các chương khác

  • Chương 2 — Variables & Types: đi sâu vào var, final, const, type inference, String interpolation, null safety basic.
  • Chương 3 — Functions & Control Flow: named parameters, required keyword — pattern xuất hiện ở mọi widget Flutter.
  • Flutter chương 1 (Setup): nhắc lại CLI toolchain nhưng với flutter wrapper thay dart.