
برای اینکه بتونیم توی فلاتر با یک کدبیس نسخه های اپ رو برای سناریو های مختلف بسازیم از Flavors استفاده میکنیم.
فرض کنید درحال توسعه اپلیکیشن با فلاتر هستید و تیم ما شامل برنامه نویس ها برای توسعه فیچر ها، تیم QA برای برسی و باگ گیری و تیم عملیاتی برای انتشار نسخه نهایی که هر تیم باید با محیط و تنظیمات جدا کار کنه به این شکل که
سرور تست داخلی + ابزارهای دیباگ فعال:Development (dev)
محیط نزدیک به واقیت + گزارش گیری فعال :Staging (staging)
محیط واقعی + امنیت و پرفورمنس کامل :Production (prod)
که این اسپلیت کردن با flavors قابل انجام هست
بدون flavor یه سری خطا های احتمالی وجود داره
انتشار اپلیکیشنی که اتصال به API که روی حالت dev هست
امکان داره روی حالت پروداکشن لاگ هارو غیرفعال نکرده باشی و ...
ولی اگر از flavors استفاده کنیم از این مشکلات جلوگیری کنیم و توی CI/CD هم بهت خیلی راحت کمک میکنه که نسخه های مختلف رو خروجی بدی
گام اول توی پوشه lib سه نقطه ورودی میسازیم که شامل
lib/ ├── main_dev.dart ├── main_staging.dart ├── main_prod.dart └── main_common.dart
اینجا سه نقطه ورودی داریم main_dev.dart, main_staging.dart, main_prod.dart که اجرا کننده فایل main_common.dart هست
حالا کد های main_common.dart ببینیم
import 'package:flutter/material.dart'; import 'src/app.dart'; import 'src/config/app_config.dart'; Future<void> mainCommon({required String env}) async { WidgetsFlutterBinding.ensureInitialized(); final config = AppConfig.forEnv(env); runApp(MyApp(config: config)); }
یه متود mainCommon ساختیم که یک String میگیره با نام env که محیط مارو مشخص میکنه
یه کانفیگ ساختیم (کدشو جلوتر میبینی)
و اپ اجرا میشه با کانفیگ مورد نظر
برای مثال فایل main_dev.dart رو ببینیم که برای بقیه ورودی ها هم به همین شکل هست
import 'main_common.dart'; void main() { mainCommon(env: 'dev'); // dev, staging, prod }
خب بریم سراغ کد کانفیگ
import 'package:flutter/material.dart'; class AppConfig { final String env; final String appName; final String baseUrl; final Color primaryColor; const AppConfig({ required this.env, required this.appName, required this.baseUrl, required this.primaryColor, }); factory AppConfig.forEnv(String env) { switch (env) { case 'dev': return const AppConfig( env: 'dev', appName: 'My App Dev', baseUrl: 'https://dev.api.myapp.ir', primaryColor: Colors.red, ); case 'staging': return const AppConfig( env: 'staging', appName: 'My App Staging', baseUrl: 'https://staging.api.myapp.ir', primaryColor: Colors.orange, ); default: return const AppConfig( env: 'prod', appName: 'My App', baseUrl: 'https://api.myapp.ir', primaryColor: Colors.green, ); } } }
توی این کلاسی که ساختیم appname، baseUrl و primaryColor رو برای هر محیط کاستومیایز کردیم
حالا وقتشه که Flavor رو توی اندروید تنظیم کنیم. برای این کار نیازه بریم به مسیر android/app/build.gradle.kts
و کد زیر
android { ... flavorDimensions += "env" productFlavors { create("dev") { dimension = "env" applicationIdSuffix = ".dev" } create("staging") { dimension = "env" applicationIdSuffix = ".staging" } create("prod") { dimension = "env" } } ... }
سه productFlavors ساختیم که dev, staging و prod که برای هر خروجی به آخر package name ما applicationIdSuffix اضافه میکنه که این موجب میشه اپلیکیشن بصورت آپدیت نیاد و جداگانه کلون بشه
توجه کنید که برای prod من هیچ applicationIdSuffix نگذاشتم چون نباید package name عوض بشه
# محیط توسعه flutter run --flavor dev -t lib/main_dev.dart # محیط تست (QA) flutter run --flavor staging -t lib/main_staging.dart # محیط انتشار flutter run --flavor prod -t lib/main_prod.dart
میتوانید برای هر flavor:
آیکون و Splash Screen متفاوت داشته باشید (با flutter_launcher_icons و flutter_native_splash)
تنظیمات امنیتی متفاوت اعمال کنید.
Feature Flag و dart-define برای فعال/غیرفعال کردن فیچرها استفاده کنید.
خب...
استفاده از flavor در Flutter یکی از بهترین روشها برای مدیریت چند محیط (dev/staging/prod) در یک کدبیسه. این کار باعث میشه تیم شما:
سریعتر نسخههای مختلف را بسازه
از اشتباهات خطرناک جلوگیری کنه
فرآیند تست و انتشار را بهینه کنه
امیدوارم که از این مطلب استفاده کرده باشید
منابع من برای این نوشته : pub.dev