شرح Serverpod : كيف تبني Backend لتطبيق Flutter بـ Dart فقط ؟

تخيل هذا السيناريو: أنت مطور Flutter، تقضي ساعات طويلة في بناء واجهة مستخدم رائعة، ثم تصل إلى مرحلة ربط التطبيق بالخادم (Backend). فجأة، تجد نفسك مضطراً لتعلم لغة جديدة، أو التعامل مع إطارات عمل معقدة، أو كتابة مئات الأسطر من أكواد الـ Boilerplate فقط لإنشاء نقطة اتصال (Endpoint) بسيطة. ناهيك عن مشاكل عدم تطابق البيانات بين العميل والخادم. هذه المعاناة اليومية تستهلك وقتك وطاقتك، وتؤخر إطلاق مشروعك.

هنا يأتي دور Serverpod كحل جذري لهذه المشكلة. في هذا المقال، سنقدم لك شرح Serverpod الشامل، وكيف يمكن لهذا الإطار أن يغير طريقة بناء تطبيقاتك بالكامل، من خلال توحيد لغة البرمجة (Dart) بين العميل والخادم.

ما هو Serverpod؟

Serverpod هو إطار عمل Backend مفتوح المصدر ومصمم خصيصاً لمطوري Flutter. الفكرة الأساسية بسيطة لكنها قوية: كتابة كود الخادم بالكامل باستخدام لغة Dart.

يتيح لك Serverpod تعريف نقاط الاتصال (Endpoints) على الخادم، ثم استدعاءها مباشرة من تطبيق Flutter الخاص بك كما لو كنت تستدعي دالة محلية، دون الحاجة لكتابة أي كود إضافي للربط. الأداة تقوم بتحليل كود الخادم وتوليد واجهة Dart للعميل وكلاسات البيانات تلقائياً.

لماذا تهتم بـ Serverpod؟

إذا كنت تتساءل عما يميز Serverpod عن غيره من الحلول، فإليك الأسباب التي تجعله يستحق وقتك:

  • لغة واحدة للجميع: استخدام Dart في كامل الـ Stack يعني تقليل التشتت (Context-switching) ومشاركة النماذج (Models) بسهولة بين التطبيق والخادم.
  • قابلية التوسع (Scalability): الإطار مصمم لينمو مع مشروعك، بدءاً من مشاريع الهواة وحتى التطبيقات التي تخدم ملايين المستخدمين النشطين، دون الحاجة لتغيير سطر واحد من الكود.
  • ORM متكامل: تعامل مع قاعدة البيانات بلغة Dart الأصيلة بدلاً من كتابة استعلامات SQL معقدة. كل شيء Type-safe مع دعم كامل لميزة Null-safety.
  • بيانات آنية (Real-time): يمكنك دفع البيانات من الخادم باستخدام Dart Streams دون القلق حول تعقيدات دورة حياة WebSocket.
  • مفتوح ومجاني: تجنب الارتباط بمزود واحد (Vendor lock-in). يمكنك نشر خادمك في أي مكان يدعم تشغيل Dart.

كيف تبدأ؟

قبل البدء، تأكد من تثبيت Flutter و Docker على جهازك (حيث نستخدم Docker لتشغيل قاعدة بيانات PostgreSQL محلياً).

لتثبيت Serverpod CLI، افتح الـ Terminal ونفذ الأمر التالي:

dart pub global activate serverpod_cli

هذا الأمر يقوم بتثبيت أداة سطر الأوامر الخاصة بـ Serverpod عالمياً على جهازك.

تحقق من نجاح التثبيت:

$ serverpod

إذا ظهرت قائمة المساعدة فالتثبيت ناجح.

إضافة VS Code (موصى بها)

إضافة Serverpod لـ VS Code تتيح تشخيصاً فورياً وتلوين صياغي لملفات النماذج في مشروعك. يمكنك تثبيتها من VS Code Marketplace أو البحث عن Serverpod مباشرةً داخل VS Code.

تثبيت Serverpod Insights (موصى به)

Serverpod Insights تطبيق مرافق يتيح لك الوصول إلى سجلات السيرفر ومؤشرات الصحة. متاح لـ Mac وWindows حالياً.

لإنشاء مشروع جديد، استخدم الأمر:

serverpod create my_project

هذا الأمر سينشئ بنية المشروع التي تتضمن كود الخادم، كود التواصل (Client)، وتطبيق Flutter جاهز للاتصال بالخادم المحلي.

 نصيحة

يجب أن يكون اسم المشروع اسم Dart package صالحاً: يبدأ بحرف صغير ويحتوي فقط على حروف صغيرة وأرقام وشرطات سفلية. مثلاً my_project صالح، أما MyCounter فغير صالح.

بعد تشغيل الأمر ستُنشأ البنية التالية:

my_project/
├── my_project_server/ # كود السيرفر
├── my_project_client/ # كود التواصل بين التطبيق والسيرفر
└── my_project_flutter/ # تطبيق Flutter جاهز للاتصال بالسيرفر المحلي

لتشغيل قاعدة البيانات والخادم، انتقل إلى مجلد الخادم ونفذ الأوامر التالية:

cd my_project/my_project_server
docker compose up -d
dart run bin/main.dart --apply-migrations

تشغيل قاعدة البيانات

ابدأ قاعدة البيانات عبر Docker:

$ cd my_project/my_project_server
$ docker compose up

لتشغيلها في الخلفية:

$ docker compose up -d

تشغيل السيرفر

عند أول تشغيل نحتاج لتطبيق الـ migrations على قاعدة البيانات:

$ cd my_project/my_project_server
$ dart run bin/main.dart --apply-migrations

السيرفر الآن متاح على http://localhost:8080 وخادم الويب على http://localhost:8082.

تشغيل تطبيق Flutter

$ cd my_project/my_project_flutter
$ flutter run -d chrome

هذه الأوامر تقوم بتشغيل قاعدة البيانات في الخلفية باستخدام Docker، ثم تشغيل الخادم وتطبيق التحديثات (Migrations) الأولية على قاعدة البيانات.

نصائح ومزالق يجب تجنبها

  • تسمية المشاريع: تأكد من أن اسم مشروعك يتبع قواعد تسمية حزم Dart (حروف صغيرة، أرقام، وشرطات سفلية فقط). اسم مثل MyProject سيؤدي إلى خطأ.
  • إدارة الحالة (State Management): تذكر أن دوال الخادم يجب أن تكون عديمة الحالة (Stateless). تجنب استخدام المتغيرات العامة (Global variables) لتخزين البيانات بين الطلبات.
  • استخدم الإضافات: نوصي بشدة بتثبيت إضافة Serverpod لـ VS Code للحصول على تلوين صياغي وتشخيص فوري لملفات النماذج (.spy.yaml).

إنشاء Endpoint Methods

مع Serverpod، استدعاء endpoint method على السيرفر بسيط مثل استدعاء دالة محلية في تطبيقك.

إنشاء مشروع جديد

serverpod create magic_recipe

💡 نصيحة

افتح دائماً المجلد الجذري للمشروع في IDE الخاص بك. هذا يُسهّل التنقل بين حزم السيرفر والتطبيق ويمنع خروج المحلل عن المزامنة عند توليد الكود.

إضافة Gemini API للمشروع

سنستخدم Google Gemini API المجاني لتوليد الوصفات. أنشئ مفتاح API من هذه الصفحة وأضفه إلى ملف config/passwords.yaml:

# config/passwords.yaml
# هذا الملف لا يُضاف إلى git. يمكنك إضافة مفاتيح API هنا بأمان.
development:
  geminiApiKey: '--- Your Gemini Api Key ---'

أضف حزمة dartantic_ai كاعتمادية للسيرفر:

$ cd magic_recipe_server
$ dart pub add dartantic_ai

إنشاء Endpoint جديد

أنشئ ملفاً جديداً في magic_recipe_server/lib/src/recipes/ باسم recipe_endpoint.dart:

import 'package:dartantic_ai/dartantic_ai.dart';
import 'package:serverpod/serverpod.dart';

/// هذا الـ endpoint يولد وصفات باستخدام Google Gemini API
class RecipeEndpoint extends Endpoint {
  /// مرر نصاً يحتوي على المكونات واحصل على وصفة
  Future<String> generateRecipe(Session session, String ingredients) async {
    final geminiApiKey = session.passwords['geminiApiKey'];
    if (geminiApiKey == null) {
      throw Exception('Gemini API key not found');
    }

    final agent = Agent.forProvider(
      GoogleProvider(apiKey: geminiApiKey),
      chatModelName: 'gemini-2.5-flash-lite',
    );

    final prompt = 'Generate a recipe using: $ingredients';
    final response = await agent.send(prompt);
    final responseText = response.output;

    if (responseText.isEmpty) {
      throw Exception('No response from Gemini API');
    }
    return responseText;
  }
}

ℹ️ معلومة

كي تتعرف Serverpod على الـ methods، يجب أن تُعيد Future أو Stream مع نوع محدد، وأن يكون أول بارامتر هو Session.

توليد الكود

$ cd magic_recipe_server
$ serverpod generate

استدعاء الـ Endpoint من العميل

بعد التوليد، استدعاء الـ endpoint من Flutter أصبح هكذا:

final result = await client.recipe.generateRecipe(
  _textEditingController.text,
);

تشغيل التطبيق

💡 نصيحة

قبل تشغيل السيرفر، تأكد أنه لا يوجد سيرفر Serverpod آخر يعمل وأن حاويات Docker من مشاريع أخرى متوقفة لتجنب تعارض المنافذ.

$ cd magic_recipe_server
$ docker compose up -d
$ dart bin/main.dart --apply-migrations
$ cd magic_recipe_flutter
$ flutter run -d chrome

النماذج والبيانات

Serverpod يأتي مع نظام نمذجة بيانات قوي يستخدم ملفات YAML سهلة القراءة. يُولّد كلاسات Dart مع كامل كود الـ serialization والـ deserialization والاتصال بقاعدة البيانات.

إنشاء نموذج جديد

أنشئ ملفاً جديداً باسم recipe.spy.yaml في magic_recipe_server/lib/src/recipes/. استخدم اللاحقة .spy.yaml للدلالة على أنه Serverpod YAML:

### وصفة مولَّدة بالذكاء الاصطناعي
class: Recipe
fields:
  ### كاتب الوصفة
  author: String
  ### نص الوصفة
  text: String
  ### تاريخ الإنشاء
  date: DateTime
  ### المكونات التي أدخلها المستخدم
  ingredients: String

يمكنك استخدام معظم أنواع Dart الأصيلة أو أي نماذج أخرى عرّفتها في ملفات YAML أخرى، بالإضافة إلى List وMap وSet مع تحديد النوع.

توليد الكود

$ cd magic_recipe_server
$ serverpod generate

سيُنشئ هذا الملف recipe.dart في مجلد lib/src/generated ويحدّث كود العميل أيضاً.

استخدام النموذج في السيرفر

حدّث الـ endpoint ليعيد كائن Recipe بدلاً من String:

import 'package:magic_recipe_server/src/generated/protocol.dart';

class RecipeEndpoint extends Endpoint {
  Future<Recipe> generateRecipe(Session session, String ingredients) async {
    // ... كود توليد الوصفة ...

    final recipe = Recipe(
      author: 'Gemini',
      text: responseText,
      date: DateTime.now(),
      ingredients: ingredients,
    );

    return recipe;
  }
}

استخدام النموذج في التطبيق

بعد إعادة تشغيل serverpod generate، يمكنك استخدام النموذج في Flutter:

final result = await client.recipe.generateRecipe(
  _textEditingController.text,
);

setState(() {
  _resultMessage = '${result.author} on ${result.date}:\n${result.text}';
});

الأنواع المدعومة

النوعالوصف
boolقيمة منطقية
intعدد صحيح
doubleعدد عشري
Stringنص
DateTimeتاريخ ووقت
ByteDataبيانات ثنائية
UuidValueمعرّف UUID
List<T>قائمة من نوع محدد
Map<K,V>قاموس من نوعين محددين
نماذج مخصصةكلاسات معرَّفة بـ .spy.yaml

العمل مع قاعدة البيانات

Serverpod يستخدم PostgreSQL للتخزين الدائم ويوفر ORM متكاملاً يتيح لك التعامل مع قاعدة البيانات بلغة Dart بالكامل.

ربط النموذج بجدول في قاعدة البيانات

لربط نموذج بجدول، أضف خاصية table إلى ملف الـ YAML:

class: Recipe
table: recipe
fields:
  author: String
  text: String
  date: DateTime
  ingredients: String

بعد تشغيل serverpod generate، ولد الـ migration:

$ cd magic_recipe_server
$ serverpod create-migration

عمليات CRUD الأساسية

إدراج سجل

var recipe = Recipe(
  author: 'Gemini',
  text: recipeText,
  date: DateTime.now(),
  ingredients: ingredients,
);
recipe = await Recipe.db.insertRow(session, recipe);

البحث بالمعرّف

var found = await Recipe.db.findById(session, recipe.id!);

البحث بشرط

var recipes = await Recipe.db.find(
  session,
  where: (r) => r.author.equals('Gemini'),
);

التحديث

recipe.text = 'نص محدَّث';
await Recipe.db.updateRow(session, recipe);

الحذف

await Recipe.db.deleteRow(session, recipe);

Transactions

await session.db.transaction((transaction) async {
  await Recipe.db.insertRow(session, recipe, transaction: transaction);
  await Ingredient.db.insertRow(session, ingredient, transaction: transaction);
});

نشر Serverpod

بعد بناء مشروعك محلياً، حان وقت النشر على بيئة الإنتاج.

خيارات النشر

Serverpod Cloud

نشر بصفر إعدادات. حالياً في مرحلة قائمة انتظار. انضم للقائمة.

Docker

كل مشروع يأتي بحاوية Docker جاهزة للنشر على أي خادم.

AWS / Google Cloud

سكريبتات Terraform جاهزة للنشر على AWS أو Google Cloud Platform.

نشر بـ Docker

إبنِ صورة Docker:

$ cd my_project_server
$ docker build -t my_project_server .

شغّل الحاوية:

$ docker run -p 8080:8080 my_project_server

نظرة عامة

Serverpod إطار عمل backend مفتوح المصدر لتطبيقات Flutter مكتوب بـ Dart. يهدف إلى تقليل الـ boilerplate ودمج كثير من مهام الـ backend المشتركة خارج الصندوق.

القدرات الرئيسية

توليد الكود التلقائي

يحلل Serverpod كود السيرفر ويولد تلقائياً واجهة Dart للعميل وكلاسات البيانات. استدعاء endpoint بعيد يصبح بسيطاً مثل استدعاء دالة محلية.

تسجيل بمستوى عالمي

أدوات تسجيل ومراقبة مدمجة تتيح لك تحديد الاستثناءات واستعلامات قاعدة البيانات البطيئة عبر واجهة سهلة الاستخدام.

Caching مدمج

تخزين مؤقت عالي الأداء وموزّع مدمج. أي كائن يمكن تخزينه مؤقتاً (primitives وlists وmaps ونماذج قابلة للتسلسل) في الذاكرة أو موزَّعاً بـ Redis.

ORM سهل الاستخدام

يوفر Serverpod ORM يستخدم أنواع Dart الأصيلة ومع null-safety لاستعلامات قاعدة البيانات. تكتب Dart بدلاً من SQL.

Migrations لقاعدة البيانات

نظام migration مدمج يحافظ على تزامن schema قاعدة البيانات مع تطور مشروعك.

رفع الملفات

دعم أصيل لرفع الملفات إلى التخزين السحابي أو قاعدة البيانات: Amazon S3 أو Google Cloud Storage أو PostgreSQL.

المصادقة

مصادقة المستخدمين جاهزة للاستخدام فوراً مع دعم تسجيل الدخول بـ Google وApple وFirebase والبريد الإلكتروني/كلمة المرور وآليات مخصصة.

بث البيانات في الوقت الفعلي

دعم للاتصالات الفورية عبر Dart streams. ادفع كائنات مُسلسَلة عبر اتصالات WebSocket آمنة للتحديثات الحية (مثل الدردشات والألعاب).

جدولة المهام

استدعاءات المستقبل في Serverpod تحل محل cron jobs المعقدة. استدعِ method في أي وقت مستقبلاً أو بعد تأخير محدد، والاستدعاءات تستمر حتى بعد إعادة تشغيل السيرفر.

خادم ويب مدمج

Serverpod يأتي مع خادم ويب حديث عالي الأداء يُسمى Relic لبناء REST APIs والـ webhooks وصفحات الويب.

تعريف Endpoints

الـ endpoints هي نقاط الدخول التي يستدعيها العملاء لتنفيذ منطق السيرفر. يُعرَّف الـ endpoint بإنشاء كلاس يمتد من Endpoint وإضافة methods غير متزامنة إليه:

import 'package:serverpod/serverpod.dart';

class GreetingEndpoint extends Endpoint {
  Future<String> hello(Session session, String name) async {
    return 'Hello $name';
  }
}

على جانب العميل:

final result = await client.greeting.hello('World');

نماذج البيانات والتسلسل

تُعرَّف نماذج البيانات في ملفات YAML بامتداد .spy.yaml وتُولَّد منها كلاسات Dart مشتركة بين السيرفر والتطبيق:

class: Company
fields:
  name: String
  foundedDate: DateTime?

التكامل مع قاعدة البيانات والـ ORM

لربط النموذج بجدول في قاعدة البيانات أضف اسم الجدول:

class: Company
table: company
fields:
  name: String
  foundedDate: DateTime?
// إدراج سجل جديد
var company = Company(name: 'Serverpod Inc.', foundedDate: DateTime.now());
company = await Company.db.insertRow(session, company);

// استرجاع بالمعرّف
var stored = await Company.db.findById(session, company.id);

المرجع: العمل مع Endpoints

الـ endpoints هي العمود الفقري لتطبيق Serverpod. هنا المرجع الشامل لكيفية تعريفها واستخدامها.

بنية الـ Endpoint

class MyEndpoint extends Endpoint {
  // يجب أن تعيد Future أو Stream
  Future<String> myMethod(Session session, String param) async {
    return 'result';
  }

  // Stream للبيانات الآنية
  Stream<String> myStream(Session session) async* {
    yield 'update 1';
    yield 'update 2';
  }
}

كائن Session

كائن Session يوفر الوصول إلى موارد السيرفر:

الخاصيةالوصف
session.dbالوصول المباشر لقاعدة البيانات
session.cachesالوصول إلى الـ cache
session.authمعلومات المصادقة
session.passwordsكلمات المرور والمفاتيح من passwords.yaml
session.logالتسجيل

التحكم في الصلاحيات

class SecureEndpoint extends Endpoint {
  // يتطلب تسجيل دخول
  @override
  bool get requireLogin => true;

  Future<String> secureMethod(Session session) async {
    return 'secure data';
  }
}

المرجع: نماذج البيانات

دليل شامل لتعريف النماذج في ملفات .spy.yaml.

كلاس بسيط

class: UserProfile
fields:
  name: String
  age: int
  email: String?  # nullable

كلاس مع جدول قاعدة البيانات

class: UserProfile
table: user_profile
fields:
  name: String
  age: int
  email: String?

العلاقات (Relations)

class: Post
table: post
fields:
  title: String
  content: String
  # علاقة مع مستخدم
  authorId: int
  author: UserProfile?, relation(field: authorId)

القوائم والأنواع المركبة

class: ShoppingCart
fields:
  items: List<CartItem>
  tags: List<String>
  metadata: Map<String, String>

التحكم في الظهور (Scopes)

class: User
table: user
fields:
  email: String
  # مخفية عن العميل
  passwordHash: String, scope: serverOnly

المرجع: قاعدة البيانات والـ ORM

دليل شامل للتعامل مع PostgreSQL عبر ORM الخاص بـ Serverpod.

الاتصال بقاعدة البيانات

إعدادات الاتصال في config/development.yaml:

database:
  host: localhost
  port: 5432
  name: my_project
  user: postgres
  password: 'my_password'

عمليات الاستعلام المتقدمة

الترتيب والتحديد

var recipes = await Recipe.db.find(
  session,
  where: (r) => r.author.equals('Gemini'),
  orderBy: (r) => r.date,
  orderDescending: true,
  limit: 10,
  offset: 0,
);

الانضمام للعلاقات (Joins)

var posts = await Post.db.find(
  session,
  include: Post.include(
    author: UserProfile.includeIfNotNull(),
  ),
);

العمليات الجماعية

// إدراج متعدد
await Recipe.db.insert(session, [recipe1, recipe2, recipe3]);

// حذف بشرط
await Recipe.db.delete(
  session,
  where: (r) => r.date.isBefore(DateTime.now().subtract(
    const Duration(days: 30),
  )),
);

Migrations

عند تغيير النماذج:

# إنشاء migration جديد
$ serverpod create-migration

# تطبيق الـ migrations عند تشغيل السيرفر
$ dart run bin/main.dart --apply-migrations

المرجع: المصادقة (Authentication)

Serverpod يوفر نظام مصادقة شامل جاهز للاستخدام مع عدة موفرين.

موفرو المصادقة المدعومون

Google

تسجيل دخول بحساب Google

Apple

تسجيل دخول بـ Apple ID

Firebase

استخدام Firebase Auth

Email

بريد إلكتروني + كلمة مرور

إعداد المصادقة

أضف حزمة المصادقة:

$ dart pub add serverpod_auth_server

التحقق من تسجيل الدخول في Endpoint

class UserEndpoint extends Endpoint {
  @override
  bool get requireLogin => true;

  Future<String> getProfile(Session session) async {
    final userId = await session.auth.authenticatedUserId();
    return 'User ID: $userId';
  }
}

المرجع: Streams والوقت الفعلي

Serverpod يدعم بث البيانات في الوقت الفعلي عبر Dart streams واتصالات WebSocket آمنة.

إنشاء Streaming Endpoint

class ChatEndpoint extends Endpoint {
  Stream<ChatMessage> messageStream(Session session, int roomId) async* {
    await for (final message in _getMessageStream(roomId)) {
      yield message;
    }
  }

  Future<void> sendMessage(
    Session session,
    int roomId,
    String text,
  ) async {
    final msg = ChatMessage(roomId: roomId, text: text);
    await session.messages.postMessage('room_$roomId', msg);
  }
}

الاستماع للـ Stream في Flutter

final stream = client.chat.messageStream(roomId);
stream.listen((message) {
  setState(() {
    messages.add(message);
  });
});

المرجع: التخزين المؤقت (Caching)

Serverpod يوفر تخزيناً مؤقتاً عالي الأداء في الذاكرة أو موزَّعاً بـ Redis.

Cache محلي

// تخزين
await session.caches.local.put(
  'user:$userId',
  userData,
  lifetime: const Duration(minutes: 5),
);

// استرجاع
final cached = await session.caches.local.get<UserData>('user:$userId');

// حذف
await session.caches.local.invalidateKey('user:$userId');

Cache موزَّع (Redis)

// تخزين في Redis
await session.caches.distributed.put(
  'global:key',
  data,
  lifetime: const Duration(hours: 1),
);

إعداد Redis

redis:
  host: localhost
  port: 6379

المرجع: التسجيل والمراقبة

Serverpod يوفر أدوات تسجيل قوية لمراقبة سلوك السيرفر وتشخيص المشكلات.

التسجيل اليدوي

// تسجيل معلومة
session.log('Processing request for user: $userId');

// تسجيل خطأ
session.log(
  'Failed to process payment',
  level: LogLevel.error,
  exception: e,
  stackTrace: stackTrace,
);

مراقبة الاستعلامات البطيئة

Serverpod يسجل تلقائياً جميع استعلامات قاعدة البيانات التي تستغرق وقتاً طويلاً. يمكنك مشاهدة هذه السجلات في Serverpod Insights.

إعدادات التسجيل

logging:
  # تسجيل الاستعلامات التي تستغرق أكثر من 100ms
  slowQueryDurationMs: 100
  # الحد الأقصى لحجم رسالة التسجيل بالبايت
  maxLogMessageSize: 10000

استراتيجية النشر

Serverpod يوفر عدة خيارات للنشر تناسب مختلف الاحتياجات.

المقارنة بين خيارات النشر

الخيارالسهولةالتحكمالتكلفة
Serverpod Cloud⭐⭐⭐⭐⭐⭐⭐⭐متغيرة
Docker (VPS)⭐⭐⭐⭐⭐⭐⭐⭐منخفضة
AWS (Terraform)⭐⭐⭐⭐⭐⭐⭐متغيرة
Google Cloud⭐⭐⭐⭐⭐⭐⭐متغيرة

متطلبات الإنتاج

  • سيرفر يدعم Docker
  • قاعدة بيانات PostgreSQL (الإصدار 14 أو أحدث)
  • Redis (اختياري، للـ distributed caching)
  • شهادة SSL/TLS للنطاق

النشر بـ Docker

كل مشروع Serverpod يأتي بـ Dockerfile و docker-compose.yaml جاهزين.

بنية ملفات Docker

my_project_server/
├── Dockerfile
├── docker-compose.yaml
└── config/
    ├── development.yaml
    ├── staging.yaml
└──     production.yaml

Dockerfile النموذجي

FROM dart:stable AS build
WORKDIR /app
COPY . .
RUN dart pub get
RUN dart compile exe bin/main.dart -o bin/server

FROM scratch
COPY --from=build /runtime/ /
COPY --from=build /app/bin/server /app/bin/
ENTRYPOINT ["/app/bin/server"]

docker-compose للإنتاج

version: '3'
services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: my_project
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: my_password
    volumes:
      - postgres_data:/var/lib/postgresql/data

  server:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - postgres

volumes:
  postgres_data:

Serverpod Insights

تطبيق مرافق قوي لمراقبة سيرفرك وتشخيص المشكلات في الوقت الفعلي.

الميزات الرئيسية

مؤشرات الصحة

مراقبة استخدام CPU والذاكرة وأداء قاعدة البيانات.

سجلات مباشرة

عرض سجلات السيرفر في الوقت الفعلي مع تصفية وبحث متقدم.

الاستعلامات البطيئة

تحديد استعلامات قاعدة البيانات التي تبطئ التطبيق.

تتبع الأخطاء

عرض الاستثناءات وstack traces بشكل مفصل.

الأنظمة المدعومة

  • macOS متاح
  • Windows متاح
  • Linux (قادم قريباً)

الاتصال بالسيرفر

Insights يتصل بسيرفرك عبر المنفذ 8081 افتراضياً. تأكد أن هذا المنفذ متاح في إعدادات الـ firewall الخاصة بك.

Serverpod Mini

نسخة مخففة من Serverpod مثالية للمشاريع الصغيرة والنماذج الأولية.

ما هو Serverpod Mini؟

Serverpod Mini هو نسخة مصغرة تعمل بدون قاعدة بيانات PostgreSQL. مثالي للـ prototyping السريع أو عندما لا تحتاج إلى استمرارية البيانات.

إنشاء مشروع Mini

$ serverpod create my_mini_project --mini

الفروقات عن Serverpod الكامل

الميزةServerpodServerpod Mini
Endpoints
توليد الكود
PostgreSQL ORM
Migrations
المصادقة
Docker مطلوب

💡 متى تستخدم Mini؟

استخدم Mini عندما تريد اختبار فكرة سريعاً، أو عند بناء API بسيط لا يحتاج لتخزين دائم. عند توسع المشروع يمكنك الترقية إلى Serverpod الكامل بسهولة.

الدعم والمجتمع

Serverpod لديه مجتمع نشط ومتنامٍ من المطورين حول العالم.

قنوات الدعم

Discord

انضم إلى خادم Discord الرسمي للحصول على المساعدة والتحدث مع المجتمع.

GitHub Issues

أبلغ عن الأخطاء أو اقترح ميزات جديدة على GitHub.

Stack Overflow

اطرح أسئلتك بوسم serverpod.

Serverpod Academy

دروس ومقاطع فيديو للتعلم من الصفر.

خارطة الطريق والمساهمة

Serverpod مشروع مفتوح المصدر ويرحب بمساهمات المجتمع.

كيفية المساهمة

1- Fork المستودع

انسخ مستودع serverpod/serverpod على GitHub.

2- أنشئ branch جديد

أنشئ branch لميزتك أو إصلاح الخطأ.

3- اكتب الاختبارات

تأكد من كتابة اختبارات تغطي التغييرات. Serverpod لديه أكثر من 5000 اختبار آلي.

4- افتح Pull Request

قدّم PR مع وصف واضح للتغييرات.

ميزات قادمة

  • Serverpod Cloud — نشر بصفر إعدادات (قائمة انتظار مفتوحة)
  • دعم Serverpod Insights على Linux
  • تحسينات على نظام الـ migrations
  • دعم موفرين مصادقة إضافيين

ℹ️ معلومة

تحقق من قائمة الـ issues على GitHub لرؤية أحدث خارطة الطريق والمهام المتاحة للمساهمة.

الخلاصة :

بعد هذا الشرح، يمكن القول إن Serverpod ليس مجرد أداة أخرى، بل هو تغيير جذري في طريقة تفكير مطوري Flutter. إذا كنت تعمل ضمن فريق صغير أو مطور مستقل (Solo Developer)، فإن استخدام Serverpod سيوفر عليك مئات الساعات من كتابة الأكواد المكررة ويقلل من احتمالية الأخطاء.

هل يستحق التجربة؟ بالتأكيد. أنصحك باستخدامه في مشروعك القادم، خاصة إذا كنت تبحث عن سرعة في التطوير دون التضحية بقابلية التوسع.

اعجبك المقال : شاركه الآن
احمد علي
احمد علي

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

المقالات: 205

اترك ردّاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *