ข้ามไปยังเนื้อหา

Build & Release

Flutter compile code เดียวกันสามแบบต่างกันขึ้นกับสิ่งที่คุณต้องการ:

flowchart LR
  debug["debug
JIT · hot reload · asserts on
(slow, dev only)"]
  profile["profile
AOT · perf tools on
(measure real speed)"]
  release["release
AOT · asserts off · optimized
(ship this)"]
build mode สามแบบและ compilation ของตัวเอง
  • Debug — JIT-compiled, hot reload, assertion เปิด, service extension ใช้ได้ ช้าและใหญ่ สำหรับ develop เท่านั้น
  • Profile — AOT-compiled เหมือน release แต่ยังมี performance tooling ติดอยู่ นี่คือที่ที่คุณวัดความเร็วจริงและตามล่า jank (อย่า profile ใน debug — ตัวเลขไม่มีความหมาย)
  • Release — AOT-compiled, assertion ถูกตัด, debugging ปิด, tree-shaken และ optimize นี่คือสิ่งที่ user ได้รับ

การแยก debug/release จริง ๆ แล้วคือการแยก compilation:

  • JIT (Just-In-Time) ใช้ใน debug compile Dart ตอนที่รัน — นั่นคือสิ่งที่ทำให้ hot reload เป็นไปได้ (swap code ใหม่เข้าไปได้ทันที)
  • AOT (Ahead-Of-Time) ใช้ใน profile และ release compile Dart เป็น native machine code ก่อนที่แอปจะ ship ผลลัพธ์คือ startup ที่เร็วและ performance ที่คาดเดาได้ แลกกับการไม่มี hot reload

Tree-shaking เกิดใน AOT build: code ที่ไม่ถูกใช้ (และที่สำคัญ icon glyph ที่ไม่ถูก reference) ถูกตัดออกเพื่อให้ binary เล็ก

Terminal window
flutter build apk --release # Android APK (direct install/testing)
flutter build appbundle --release # Android App Bundle (Play Store)
flutter build ipa --release # iOS archive (App Store)
flutter build web --release # web bundle

แต่ละ target สร้าง artifact คนละแบบจาก Dart source เดียวกัน — framework abstract platform ออกไป ส่วน build step ทำให้ออกมาเป็นจริงบนแต่ละ platform

Flavor (Android) / scheme (iOS) ให้ codebase เดียวสร้าง build แบบ dev, staging และ production ด้วย config ต่างกัน — API endpoint, app ID, icon — โดยไม่ต้องแตก branch ของ code

Terminal window
flutter run --flavor dev --dart-define=API_URL=https://dev.api.example.com
flutter build apk --flavor prod --dart-define=API_URL=https://api.example.com

--dart-define ส่ง compile-time constant ที่ code อ่านผ่าน String.fromEnvironment — วิธีที่สะอาดในการ inject ค่าแต่ละ environment โดยไม่ commit secret เข้า source

ควรใช้ build mode ไหนในการวัด performance จริง?
ทำไม hot reload ใช้ได้ใน debug แต่ไม่ใช่ release?
tree-shaking ทำอะไรใน release build?
flavor ใช้ทำอะไร?