شارك المقالة

تشغيل Firebase CLI مع أكثر من firebase cli flutter باستخدام FlutterFire

عند بناء تطبيق Flutter احترافي، غالبًا ستحتاج إلى أكثر من بيئة تشغيل مثل بيئة التطوير dev وبيئة الاختبار staging وبيئة الإنتاج production. ولكل بيئة قد تحتاج إلى مشروع Firebase مختلف، أو على الأقل إعدادات Firebase مختلفة، حتى لا تختلط بيانات التطوير مع بيانات المستخدمين الحقيقيين.

هنا تظهر أهمية استخدام Firebase CLI و FlutterFire CLI مع أكثر من Flavor في Flutter. فبدلًا من الاعتماد على ملف Firebase واحد فقط، يمكنك إنشاء إعدادات مستقلة لكل Flavor، مثل:

  • firebase_options_dev.dart
  • firebase_options_staging.dart
  • firebase_options_prod.dart

بهذه الطريقة يستطيع كل Flavor الاتصال بمشروع Firebase المناسب له دون حدوث تداخل بين البيئات.

ما المقصود بـ Flavor في Flutter؟

الـ Flavor في Flutter هو طريقة لإنشاء أكثر من نسخة من نفس التطبيق باستخدام نفس الكود الأساسي، لكن مع إعدادات مختلفة. على سبيل المثال، يمكنك امتلاك نسخة تطوير ونسخة إنتاج من التطبيق، وكل نسخة لها:

  • اسم تطبيق مختلف.
  • applicationId مختلف في Android.
  • Bundle Identifier مختلف في iOS.
  • ملفات Firebase مختلفة.
  • API Base URL مختلف.
  • أيقونة أو إعدادات خاصة بكل بيئة.

هذه الطريقة مفيدة جدًا عند العمل على تطبيقات حقيقية، لأنها تمنع استخدام بيانات الإنتاج أثناء التطوير أو الاختبار.

لماذا تحتاج Firebase مختلف لكل Flavor؟

استخدام Firebase واحد لكل البيئات قد يسبب مشاكل كثيرة، مثل:

  • اختلاط بيانات المستخدمين الحقيقيين مع بيانات الاختبار.
  • إرسال إشعارات تجريبية إلى مستخدمي الإنتاج بالخطأ.
  • تسجيل أخطاء التطوير داخل Crashlytics الخاص بالإنتاج.
  • صعوبة تحليل بيانات Analytics لكل بيئة بشكل مستقل.
  • صعوبة اختبار Authentication أو Firestore أو Remote Config بأمان.

لذلك، من الأفضل غالبًا إنشاء مشروع Firebase مستقل لكل Flavor، أو على الأقل تطبيق Firebase مختلف لكل بيئة.

المتطلبات قبل البدء

قبل تنفيذ الخطوات، تأكد من توفر المتطلبات التالية:

  • مشروع Flutter يعمل بشكل صحيح.
  • وجود Flavors معدّة مسبقًا داخل Android و iOS.
  • تثبيت Firebase CLI.
  • تثبيت FlutterFire CLI.
  • تسجيل الدخول إلى Firebase باستخدام الأمر firebase login.
  • وجود مشاريع Firebase أو تطبيقات Firebase المناسبة لكل Flavor.

توصي وثائق Firebase الرسمية باستخدام FlutterFire CLI لتوليد ملف إعدادات Firebase الخاص بتطبيق Flutter، ويكون الملف الافتراضي غالبًا باسم firebase_options.dart.

تثبيت Firebase CLI و FlutterFire CLI

إذا لم تكن قد ثبتّ الأدوات بعد، يمكنك تثبيت Firebase CLI ثم تسجيل الدخول:

firebase login

ثم قم بتثبيت FlutterFire CLI:

dart pub global activate flutterfire_cli

بعد ذلك يمكنك التأكد من أن الأداة تعمل من خلال:

flutterfire --version

الخطوة الأولى: تعديل applicationId في Android

حتى تتمكن من تشغيل Firebase CLI مع أكثر من Flavor في Flutter، يجب أن يكون لكل Flavor معرّف تطبيق مختلف. في Android يكون هذا المعرّف هو applicationId.

انتقل إلى الملف التالي:

android/app/build.gradle

ثم ابحث عن:

applicationId

وغالبًا ستجده داخل defaultConfig بهذا الشكل:

defaultConfig {
    applicationId "com.example.myapp"
    minSdkVersion 23
    targetSdkVersion 35
    versionCode flutterVersionCode.toInteger()
    versionName flutterVersionName
}

قم بتغيير applicationId إلى المعرّف الجديد الخاص بالـ Flavor الذي تريد ربطه مع Firebase.

defaultConfig {
    applicationId "com.example.myapp.dev"
    minSdkVersion 23
    targetSdkVersion 35
    versionCode flutterVersionCode.toInteger()
    versionName flutterVersionName
}

إذا كنت تستخدم أكثر من Flavor داخل productFlavors، فيمكنك جعل كل Flavor يمتلك applicationIdSuffix أو applicationId مختلفًا حسب طريقة إعداد مشروعك.

flavorDimensions "default"

productFlavors {
    dev {
        dimension "default"
        applicationIdSuffix ".dev"
        resValue "string", "app_name", "My App Dev"
    }

    prod {
        dimension "default"
        resValue "string", "app_name", "My App"
    }
}

الخطوة الثانية: تعديل Bundle Identifier في iOS

في iOS يجب أيضًا تغيير معرّف التطبيق حتى يتوافق مع Firebase. يمكنك تعديل ذلك من داخل Xcode، أو من خلال ملف المشروع مباشرة.

انتقل إلى الملف التالي:

ios/Runner.xcodeproj/project.pbxproj

ثم قم بالبحث عن المعرّف القديم الخاص بتطبيقك واستبدله بالمعرّف الجديد الخاص بالـ Flavor.

يمكنك استخدام الاختصار:

Ctrl + R

ثم استبدل الـ Bundle Identifier القديم بالجديد، مثل:

com.example.myapp

إلى:

com.example.myapp.dev

انتبه جيدًا عند تعديل ملف project.pbxproj يدويًا، لأن أي خطأ في البنية قد يسبب مشاكل في فتح المشروع داخل Xcode. لذلك من الأفضل أخذ نسخة احتياطية أو استخدام Git قبل التعديل.

الخطوة الثالثة: تنفيذ flutterfire configure

بعد تعديل applicationId في Android و Bundle Identifier في iOS، قم بتنفيذ الأمر التالي من جذر مشروع Flutter:

flutterfire configure

سيبدأ FlutterFire CLI في إعداد Firebase للتطبيق. أثناء العملية قد تظهر لك الرسالة التالية:

You have an existing firebase.json file and possibly already configured your project for Firebase.
Would you prefer to reuse the values in your existing firebase.json file to configure your project?

في هذه الحالة اختر:

n

أي اختر الرفض، حتى لا يعيد استخدام القيم القديمة الموجودة في ملف firebase.json. هذا مهم عند إعداد Flavor جديد، لأنك تريد توليد إعدادات Firebase جديدة ومناسبة للمعرّفات الجديدة.

الخطوة الرابعة: تحديد منصات المشروع

بعد ذلك سيطلب منك FlutterFire CLI تحديد المنصات التي تريد إعداد Firebase لها، مثل:

  • Android
  • iOS
  • Web
  • macOS
  • Windows

اختر المنصات التي يدعمها مشروعك فقط. على سبيل المثال، إذا كان تطبيقك يعمل على Android و iOS فقط، فاختر:

android
ios

بعد انتهاء العملية، سيقوم FlutterFire CLI غالبًا بتوليد ملف:

lib/firebase_options.dart

كما قد يقوم بتوليد أو تحديث ملفات Firebase الخاصة بالمنصات مثل:

  • android/app/google-services.json
  • ios/Runner/GoogleService-Info.plist

الخطوة الخامسة: إعادة تسمية ملف firebase_options

بعد توليد ملف firebase_options.dart، قم بإعادة تسميته باسم يوضح البيئة أو الـ Flavor الخاص به. على سبيل المثال:

firebase_options_dev.dart

ثم افتح الملف وابحث عن الكلاس:

DefaultFirebaseOptions

وقم بتغييره إلى اسم خاص بالبيئة، مثل:

DefaultFirebaseOptionsDev

على سبيل المثال، بدلًا من:

class DefaultFirebaseOptions {
  static FirebaseOptions get currentPlatform {
    // options
  }
}

اجعله:

class DefaultFirebaseOptionsDev {
  static FirebaseOptions get currentPlatform {
    // options
  }
}

بهذه الطريقة يمكنك امتلاك أكثر من ملف Firebase Options داخل مجلد lib دون تعارض في أسماء الكلاسات.

الخطوة السادسة: تكرار العملية لكل Flavor

بعد الانتهاء من Flavor الأول، كرر نفس الخطوات مع باقي البيئات. على سبيل المثال:

  • غيّر applicationId إلى معرّف بيئة التطوير.
  • نفّذ flutterfire configure.
  • أعد تسمية الملف إلى firebase_options_dev.dart.
  • غيّر اسم الكلاس إلى DefaultFirebaseOptionsDev.

ثم كرر العملية مع بيئة الإنتاج:

  • غيّر applicationId إلى معرّف الإنتاج.
  • نفّذ flutterfire configure.
  • أعد تسمية الملف إلى firebase_options_prod.dart.
  • غيّر اسم الكلاس إلى DefaultFirebaseOptionsProd.

وفي النهاية قد يصبح لديك ملفات بهذا الشكل:

lib/firebase_options_dev.dart
lib/firebase_options_staging.dart
lib/firebase_options_prod.dart

الخطوة السابعة: تهيئة Firebase حسب الـ Flavor

بعد تجهيز ملفات Firebase Options، يمكنك استخدام الملف المناسب في نقطة تشغيل كل Flavor. على سبيل المثال، يمكنك إنشاء ملفات تشغيل مختلفة:

lib/main_dev.dart
lib/main_prod.dart

داخل ملف main_dev.dart:

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

import 'firebase_options_dev.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp(
    options: DefaultFirebaseOptionsDev.currentPlatform,
  );

  runApp(const MyApp());
}

وداخل ملف main_prod.dart:

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

import 'firebase_options_prod.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp(
    options: DefaultFirebaseOptionsProd.currentPlatform,
  );

  runApp(const MyApp());
}

بهذا الشكل يتم تشغيل كل Flavor بإعدادات Firebase المناسبة له.

تشغيل التطبيق حسب Flavor

يمكنك تشغيل Flavor التطوير مثلًا باستخدام:

flutter run --flavor dev -t lib/main_dev.dart

وتشغيل Flavor الإنتاج باستخدام:

flutter run --flavor prod -t lib/main_prod.dart

ويمكنك أيضًا إضافة هذه الأوامر داخل إعدادات محرر الكود مثل VS Code أو Android Studio لتسهيل التشغيل.

تنظيم ملفات Firebase في Android

بالنسبة إلى Android، بعد توليد أي ملف google-services.json، يجب نقله إلى المسار المناسب للـ Flavor حتى لا تحدث مشاكل أو تعارضات.

بدلًا من ترك الملف فقط داخل:

android/app/google-services.json

يمكنك تنظيم الملفات حسب الـ Flavor بهذا الشكل:

android/app/src/dev/google-services.json
android/app/src/staging/google-services.json
android/app/src/prod/google-services.json

بهذه الطريقة يستخدم كل Flavor ملف Firebase الخاص به عند البناء.

ضع صورة توضيحية هنا لمسارات ملفات Android بعد النقل:

Firebase CLI

تنظيم ملفات Firebase في iOS

بالنسبة إلى iOS، يجب أيضًا تنظيم ملفات GoogleService-Info.plist الخاصة بكل Flavor. يمكن أن يكون لديك مثلًا:

ios/Runner/Firebase/dev/GoogleService-Info.plist
ios/Runner/Firebase/staging/GoogleService-Info.plist
ios/Runner/Firebase/prod/GoogleService-Info.plist

بعد ذلك تأكد من أن كل Scheme أو Build Configuration في Xcode يستخدم الملف الصحيح. يمكن تنفيذ ذلك يدويًا من Xcode أو من خلال Build Script ينسخ ملف GoogleService-Info.plist المناسب إلى المكان المطلوب أثناء البناء.

ضع صورة توضيحية هنا لإعداد ملفات iOS:

تشغيل Firebase CLI مع أكثر من Flavor في Flutter باستخدام FlutterFire

مثال على Build Script لاختيار ملف iOS المناسب

يمكنك استخدام Script داخل Xcode لنسخ ملف Firebase المناسب حسب البيئة. المثال التالي توضيحي وقد تحتاج إلى تعديله حسب أسماء الـ Schemes لديك:

if [ "${CONFIGURATION}" == "Debug-dev" ]; then
  cp "${PROJECT_DIR}/Runner/Firebase/dev/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
elif [ "${CONFIGURATION}" == "Release-prod" ]; then
  cp "${PROJECT_DIR}/Runner/Firebase/prod/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
fi

الفكرة هنا هي أن يتم نسخ ملف GoogleService-Info.plist الصحيح أثناء عملية البناء، حتى يتصل التطبيق بمشروع Firebase المناسب.

مشكلة إعادة استخدام firebase.json

عند تشغيل flutterfire configure أكثر من مرة، قد يحاول FlutterFire CLI إعادة استخدام الإعدادات الموجودة في firebase.json. لذلك تظهر الرسالة:

Would you prefer to reuse the values in your existing firebase.json file to configure your project?

عند إعداد Flavor جديد، الأفضل اختيار:

n

لأنك تريد إنشاء إعدادات جديدة بناءً على applicationId و Bundle Identifier الجديدين، وليس الاعتماد على القيم القديمة.

أخطاء شائعة أثناء إعداد Firebase مع Flavors

1. استخدام نفس applicationId لكل البيئات

إذا كان أكثر من Flavor يستخدم نفس applicationId، فقد يربط FlutterFire نفس تطبيق Firebase أو يسبب تعارضًا في ملفات الإعداد.

2. نسيان تغيير Bundle Identifier في iOS

حتى لو كان Android يعمل بشكل صحيح، قد يفشل iOS إذا بقي Bundle Identifier القديم أو إذا لم يكن مطابقًا للتطبيق المسجل في Firebase.

3. ترك google-services.json في المسار الخطأ

عند استخدام Flavors في Android، من الأفضل وضع كل ملف google-services.json داخل مجلد الـ Flavor المناسب، مثل:

android/app/src/dev/google-services.json

4. عدم تغيير اسم كلاس DefaultFirebaseOptions

إذا كان لديك أكثر من ملف Firebase Options وكلها تحتوي على نفس اسم الكلاس DefaultFirebaseOptions، فقد يحدث تعارض عند الاستيراد أو الاستخدام. لذلك من الأفضل تسمية كل كلاس حسب البيئة.

5. تشغيل Flavor بملف main غير مناسب

إذا شغّلت Flavor التطوير لكن استخدمت main_prod.dart، فقد يتصل التطبيق بمشروع Firebase الخاص بالإنتاج بالخطأ.

أفضل هيكلة مقترحة للملفات

يمكنك تنظيم ملفات المشروع بهذا الشكل:

lib/
  main_dev.dart
  main_staging.dart
  main_prod.dart
  firebase_options_dev.dart
  firebase_options_staging.dart
  firebase_options_prod.dart

android/
  app/
    src/
      dev/
        google-services.json
      staging/
        google-services.json
      prod/
        google-services.json

ios/
  Runner/
    Firebase/
      dev/
        GoogleService-Info.plist
      staging/
        GoogleService-Info.plist
      prod/
        GoogleService-Info.plist

هذه الهيكلة تجعل كل بيئة واضحة ومنفصلة، وتقلل احتمالية استخدام ملف Firebase خاطئ.

نصائح مهمة قبل الاعتماد في الإنتاج

  • استخدم مشروع Firebase منفصل لكل بيئة إن أمكن.
  • لا تستخدم بيانات الإنتاج أثناء التطوير.
  • تأكد من أن كل applicationId في Android مطابق لتطبيق Firebase الصحيح.
  • تأكد من أن كل Bundle Identifier في iOS مطابق لتطبيق Firebase الصحيح.
  • اختبر كل Flavor بشكل منفصل قبل رفع التطبيق.
  • تأكد من أن Crashlytics و Analytics متصلان بالبيئة الصحيحة.
  • لا تنسَ تحديث ملفات Firebase عند إضافة خدمات جديدة.
  • استخدم Git لمراجعة التغييرات بعد كل تشغيل لـ flutterfire configure.

متى تعيد تشغيل flutterfire configure؟

بحسب توثيق Firebase الرسمي، يُنصح بإعادة تشغيل flutterfire configure عند إضافة منصة جديدة، أو عند استخدام خدمة Firebase جديدة تتطلب إعدادات إضافية، أو عند الحاجة إلى تحديث إعدادات Firebase داخل التطبيق.

لذلك إذا أضفت لاحقًا خدمات مثل:

  • Firebase Authentication
  • Cloud Firestore
  • Firebase Crashlytics
  • Firebase Performance Monitoring
  • Firebase Cloud Messaging

فقد تحتاج إلى إعادة تشغيل الأمر للتأكد من أن الإعدادات محدثة.

الخلاصة

إعداد Firebase CLI و FlutterFire CLI مع أكثر من Flavor في Flutter يحتاج إلى بعض التنظيم، لكنه يصبح سهلًا بمجرد فهم الفكرة الأساسية: كل Flavor يجب أن يمتلك معرّف تطبيق خاص به، وملفات Firebase مستقلة، وملف firebase_options مناسب.

ابدأ بتعديل applicationId في Android، ثم عدّل Bundle Identifier في iOS، وبعدها نفّذ flutterfire configure. عند ظهور رسالة إعادة استخدام firebase.json اختر n، ثم حدد المنصات المطلوبة، وأعد تسمية ملف firebase_options.dart حسب البيئة.

بعد ذلك انقل ملفات Android و iOS إلى أماكنها المناسبة لكل Flavor، وتأكد من أن كل بيئة تستخدم إعدادات Firebase الصحيحة. بهذه الطريقة يمكنك فصل بيئة التطوير عن الإنتاج، وتقليل الأخطاء، وتحسين تنظيم مشروع Flutter بشكل احترافي.

المصادر


مزيد من المقالات : لا تضيّع وقتك في تصميم أفاتارات! هذا plugin في Flutter يُنشئ صورًا رمزية SVG مخصصة تلقائيًا لكل مستخدم
شاهد أيضًا
مقالات ذات صلة

🚫 مانع الإعلانات مفعل

يجب إيقاف مانع الإعلانات لاستكمال تصفح الموقع