Setup Flavors/Environments to Flutter projects : PART 2

แยก Environment Dev/Staging/Production ให้กับ Project Flutter กันเถอะ

Nawin P.
3 min readAug 3, 2022

จาก พาร์ทก่อนหน้า เราได้ทำการ Setup application เราจน Run แยก Environment ได้เรียบร้อยแล้ว ตามเข้าไปอ่านได้จากลิ้งค์นี้ครับ

Setup Flavors/Environments to Flutter projects : PART 1

โดยในพาร์ท 2 นี้เราจะมาทำส่วนที่สำคัญอีกสองส่วนก็คือ

  • 1. Add AppIcon to each Environment
  • 2. Config Environment data

Add AppIcon to each Environment

จาก Part 1 เราได้ทำการ install library ตัวหนึ่งที่ชื่อว่า flutter_launcher_icons กันไปแล้วใช่มั้ยครับ เนี่ยแหละ พระเอกของงานนี้เลย เจ้าตัว lib ตัวนี้จะทำการ generate icon ให้เราครับเพียงเเค่เราใส่รูปที่เราต้องการเป็น Icon ไปให้ มันก็จะ Generate all size ทั้งหมดให้เราเลย มาดูขั้นตอนกันครับ

  1. install library หากใครยังไม่ได้ลงในนะครับ
flutter_launcher_icons: ^0.9.3

2. เอารูปที่เราต้องการจะเป็น มาใส่ไว้ใน folder asset ก่อนครับ โดยไปที่ /assets สร้าง folder ชื่อ icons เพิ่มขึ้นมาและใส่รูปที่เราต้องการเข้าไป ตามตัวอย่างจะได้ประมาณนี้ครับ

AppIcons

3. เพิ่มไฟล์ flutter_launcher_icons สองไฟล์ด้านล่างใน project เลยครับ ( ใครงงเรื่อง Project structure กลับไปดู part 1 ได้นะครับ )

  • flutter_launcher_icons-development.yaml
flutter_launcher_icons-development.yaml
  • flutter_launcher_icons-production.yaml

4. หลังจากนั้นพิมพ์คำสั่งตามนี้ครับ

flutter pub run flutter_launcher_icons:main -f flutter_launcher_icons*

หลังจาก command ด้านบนแล้วทาง lib จะ Generate App Icon ตาม Size ที่ตามแต่ละ OS ต้องการเลยครับ สามารถเข้าไปดูได้ที่

Android: app → src → development / production

iOS : assets folder → AppIcon

Generated App Icon

5. หลังจากนั้นเราต้องไปเซตบอกกับตัว iOS Project ว่าจะอัพเดตรูป AppIcons ของแต่ละ Environment ให้ ** สำหรับ Android หลังจากเราเสร็จข้อ 4. เราไม่ต้องทำอะไรเเล้วครับ น้อง Auto Map รูปภาพกับ flavors ให้อัตโนมัติเลย

วิธีการ Map AppIcons iOS ตามนี้เลยครับ

กดเข้าโปรเจกต์ → กด Target “Runner” → กด Tab “Build Setting” → Search คำว่า Primary App Icon Set Name → แก้ไขชื่อ AppIcons ตาม Configuration ในรูปได้เลยครับ

Debug-Development : AppIcon-Development

Release-Development : AppIcon-Development

Debug-Production : AppIcon-Production

Release-Production : AppIcon-Production

ง่าย ๆ ก็คือเซตรูปที่เราต้องการตาม Environment นั่นเเหละครับ

6. ลองรัน Application. ขึ้นมาดูครับ เราจะได้เห็นได้ว่า Application Icon เราเปลี่ยนไปเเล้ว เย้ !

Result

Config Environment Data

จุดประสงค์หลักของบทความนี้เลยก็คือการแยก Environment หรือการแยก Config ให้แตกต่างกันตาม env ที่รันอยู่ ยกตัวอย่างเช่น การเรียกใช้ API ซึ่งในโลกความเป็นจริงเราต้องมีการแยกอยู่แล้วระหว่าง Dev กับ Production ไม่งั้น Test Production ตายแน่นอน

Ex. API Endpoint

Example of call api for each development

จากรูปตัวอย่างผมจะทำการแยก API Endpoint ระหว่าง Development และ Production

โดยใน Development จะยิง API เส้น https://dev.nawin.com/api 
แต่ production จะยิง https://nawin.com/api

แต่จะแยกยังไงละ ???

GetIt is Coming…

ประเด็นสำคัญ ของการแยก Environments คือ Environment Data ต้องสามารถเข้าถึงจากที่ใดก็ได้ในโปรเจกต์ ตัว Library ที่จะมาช่วยเราในเรื่องนี้ก็คือ GetIt เดิมทีแล้ว GetIt เป็น library ที่เกิดมาเพื่อทำ Service Locator แต่เราก็สามารถนำมาประยุกต์ใช้กับการแยก Env ได้เช่นกัน ทำยังไป ..ไปดูกันครับ

  1. ขั้นตอนแรกลง library ก่อนสำหรับคนที่ยังไม่ได้ลงตอน part 1
get_it: ^7.2.0

2. ถัดมาเราจะทำการสร้างไฟล์ Config เพื่อที่จะได้รวบรวมตัวแปรที่เป็น Env variable ไว้ทีเดียวเลย จะได้แก้ไขง่าย ๆ ครับ ก่อนอื่นเราสร้าง BaseConfig.dart เป็นคลาสแม่มาก่อนครับ

BaseConfig.dart

ถัดมาเราจะสร้างไฟล์อีกสองไฟล์คือ ConfigDevelopment.dart และ ConfigProduction.dart เพื่อทำการแยก Config สำหรับทั้งสอง Environment นั่นเอง โดยที่ทั้งสองไฟล์จะทำการ Inherite ตัว BaseConfig มาด้วยเพื่อให้ได้ค่าที่เหมือนกันเสมอ

ConfigDevelopment.dart
ConfigProduction.dart

หลังจากสร้างเสร็จเราจะได้ไฟล์ทั้งหมดประมาณนี้นะครับ ** หากใครงง Project Structure ย้อนกลับไปดู part 1 ก่อนนะครับ

File structure of configs folder

3. ขั้นตอนถัดมาเราจะทำการ Initial ตัว GetIt กันครับ ขั้นตอนแรกให้เราสร้าง Class สำหรับเอาไว้เป็นตัว Setup ก่อนครับ ในที่นี้ผมจะตั้งชื่อไฟล์ di.dart นะครับเพราะจริง ๆ แล้ว GetIt สามารถนำไปประยุกต์ใช้เป็น Depency Injection ก็ได้เช่นกันครับ จะได้หน้าตาประมาณนี้ครับ

di.dart

เป็นอันเสร็จเรียบร้อยครับผมสำหรับการ Setup configuration file เดียวเราไปลองเรียกใช้กันดีกว่า

วิธีการเรียกใช้ก็ง่ายมาก ๆ ครับ เรากลับไปยังไฟล์ main_development.dart และ main_production.dart กันครับ และเพิ่มโค้ดชุดนี้ลงไปครับ

// main_production.dart
// ยกตัวอย่าง main_production ใน main development ก็เปลี่ยนแค่คำว่า "production" => "development" เท่านั้นเลยครับ
void main() {DIConfigurator.setup(flavor: "production"); // setup service locatorsApiManager.instance.initial(); // initial api manager classrunApp(const App(flavor: "production"));}

ตัวอย่างการเรียกใช้ผมจะ ยกตัวอย่างการสร้างไฟล์ API Manager มาสักตัวเเล้วกันนะครับ โดยในไฟล์นี้จะทำการเรียก baseEndpoint จากไฟล์ config ครับ และทำการ log ออกมาว่ามันแยกตาม environment ที่เราทำกันไว้มั้ยนะครับ.

Example of api

ลองรันแอปพลิเคชันขึ้นมาเราจะสังเกตุเห็นใน DEBUG CONSOLE ว่ามี endpoint ที่เราตั้งค่าไว้โผล่มาแล้ว ซึ่งมันแยก endpoint ได้ถูกต้องง เย่ๆๆๆ

Production env build’s debug console
Development env build’s debug console

หากอยากเพิ่ม environment variables อีกก็สามารถเข้าไปเพิ่มได้ในไฟล์ config ของแต่ละ env ได้เลย โครตจะ Easy แล้วหลังจากนี้

เป็นอันจบสิ้นเรียบร้อยสำหรับ Series นี้ครับผม ขอบคุณทุกการอ่านมาก ๆ ครับ บทความนี้ผมไม่ได้เผยแพร่ที่ไหน เขียนไว้เพื่อโน้ตความทรงจำ แต่ถ้าท่านใดอ่านแล้วไปใช้ได้จริง ก็ปรบมือสักแปะสองแปะ พอเป็นพิธีก็ได้ครับ

--

--