Hazem Mohammed

Next.js 16Supabase RealtimeServer ActionsServer ComponentsWebSocketsPostgresNext.js Supabase

بناء تطبيقات الزمن الحقيقي مع Next.js 16 و Supabase: دليل معماري متكامل

Hazem Mohammed
٤ مارس ٢٠٢٦
بناء تطبيقات الزمن الحقيقي مع Next.js 16 و Supabase: دليل معماري متكامل

مقدمة

في عالم تطوير الويب الحديث، لم تعد الميزات الفورية مجرد ترف، بل أصبحت توقعًا أساسيًا. سواء كانت تطبيقات دردشة، أو لوحات تحكم حية، أو أنظمة إشعارات، فإن القدرة على عكس تغييرات البيانات فور حدوثها أمر بالغ الأهمية. يتيح الجمع بين Next.js 16، مع نموذج مكونات الخادم (Server Components) وإجراءات الخادم (Server Actions)، وخدمة Supabase Realtime القوية، للمطورين إنشاء هذه التجارب بسلاسة وكفاءة لا مثيل لهما. يستعرض هذا الدليل التقني كيفية بناء تطبيق Next.js قوي يستفيد من بث تغييرات قاعدة بيانات Postgres مباشرة إلى العميل.

ما هي خدمة Supabase Realtime ولماذا نستخدمها مع Next.js؟

Supabase Realtime هي خدمة تتيح لك الاستماع إلى تغييرات قاعدة بيانات Postgres الخاصة بك - عمليات الإدراج (INSERT)، والتحديث (UPDATE)، والحذف (DELETE) - عبر WebSockets. بدلاً من الاستقصاء المستمر (polling) لقاعدة البيانات بحثًا عن تغييرات، يقوم Supabase بإعلام تطبيقك فور حدوثها.

عندما يقترن هذا بـ Next.js 16، نحصل على أفضل ما في العالمين:

  1. التحميل الأولي من الخادم (SSR): يتم عرض البيانات الأولية بواسطة مكون خادم (Server Component)، مما يوفر تحميلًا أوليًا سريعًا وتحسينًا لمحركات البحث (SEO).
  2. التحديثات من العميل: بمجرد تحميل الصفحة، يتولى مكون العميل (Client Component) مسؤولية الاشتراك في تحديثات الزمن الحقيقي، مما يضمن بقاء واجهة المستخدم متزامنة مع قاعدة البيانات دون الحاجة إلى إعادة تحميل الصفحة بالكامل.
  3. تعديل البيانات الآمن: تُستخدم إجراءات الخادم (Server Actions) لمعالجة عمليات إرسال النماذج وتعديل البيانات، مما يضمن تشغيل منطق الأعمال بأمان على الخادم.

التنفيذ خطوة بخطوة

لنقم ببناء مثال عملي: قائمة مهام (todos) يتم تحديثها في الزمن الحقيقي. أولاً، تأكد من تمكين النسخ المتماثل (Replication) لجدول todos في واجهة تحكم Supabase.

1. إعداد عميل Supabase

للتكامل السلس مع العرض من جانب الخادم (SSR) وإجراءات الخادم، نحتاج إلى طريقتين لإنشاء عميل Supabase: واحدة للمكونات من جانب العميل وواحدة للبيئات من جانب الخادم (مكونات الخادم، إجراءات الخادم، مسارات API).

// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr'

export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  )
}
// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'

export function createClient() {
  const cookieStore = cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        get(name: string) {
          return cookieStore.get(name)?.value
        },
      },
    }
  )
}

2. جلب البيانات الأولية باستخدام مكون خادم

ستقوم صفحتنا الرئيسية (app/page.tsx) بدور مكون خادم لجلب قائمة المهام الأولية وتمريرها إلى مكون العميل.

// app/page.tsx
import { createClient } from '@/lib/supabase/server';
import RealtimeTodos from './realtime-todos';

// Important for Server Actions and Realtime: revalidate = 0
export const revalidate = 0;

export default async function Home() {
  const supabase = createClient();
  const { data: todos } = await supabase.from('todos').select();

  return (
    <main>
      <h1>Realtime Todos</h1>
      <RealtimeTodos serverTodos={todos ?? []} />
    </main>
  );
}

3. الاشتراك في التحديثات في مكون العميل

هذا المكون سيستلم البيانات الأولية كخاصية (prop)، ثم يقوم بإنشاء اشتراك في الزمن الحقيقي لتحديث حالته الداخلية عند وصول مهام جديدة.

// app/realtime-todos.tsx
'use client';

import { useEffect, useState } from 'react';
import { createClient } from '@/lib/supabase/client';
import type { Database } from '@/lib/database.types';

type Todo = Database['public']['Tables']['todos']['Row'];

export default function RealtimeTodos({ serverTodos }: { serverTodos: Todo[] }) {
  const [todos, setTodos] = useState(serverTodos);
  const supabase = createClient();

  useEffect(() => {
    setTodos(serverTodos);
  }, [serverTodos]);

  useEffect(() => {
    const channel = supabase
      .channel('realtime todos')
      .on(
        'postgres_changes',
        { event: 'INSERT', schema: 'public', table: 'todos' },
        (payload) => {
          setTodos((currentTodos) => [...currentTodos, payload.new as Todo]);
        }
      )
      .subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, [supabase]);

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

4. تعديل البيانات باستخدام إجراءات الخادم (Server Actions)

أخيرًا، نضيف نموذجًا يستخدم إجراء خادم لإدراج مهمة جديدة. سيؤدي هذا الإدراج إلى تشغيل بث الزمن الحقيقي الذي يستمع إليه مكون RealtimeTodos.

// app/add-todo-form.tsx
import { createClient } from '@/lib/supabase/server';
import { revalidatePath } from 'next/cache';

export default function AddTodoForm() {
  const addTodo = async (formData: FormData) => {
    'use server';
    const title = formData.get('title') as string;
    if (!title) return;

    const supabase = createClient();
    await supabase.from('todos').insert({ title });

    // Revalidate the path to refetch server data
    revalidatePath('/'); 
  };

  return (
    <form action={addTodo}>
      <input type="text" name="title" placeholder="New todo..." required />
      <button type="submit">Add</button>
    </form>
  );
}

// Don't forget to add this component to your page.tsx

حالات الاستخدام في العالم الحقيقي

هذا النمط المعماري مثالي لـ:

  • تطبيقات الدردشة: حيث تظهر الرسائل الجديدة فورًا لجميع المشاركين.
  • لوحات المعلومات التحليلية الحية: عرض المقاييس التي يتم تحديثها في الوقت الفعلي.
  • خلاصات الإشعارات: إعلام المستخدمين بالأحداث الجديدة دون الحاجة إلى تحديث الصفحة.
  • أدوات التعاون: مثل المستندات المشتركة أو لوحات كانبان حيث يمكن لعدة مستخدمين رؤية التغييرات في نفس الوقت.

خاتمة

يوفر الدمج بين Supabase Realtime و Next.js 16 App Router حلاً قويًا وأنيقًا لبناء تجارب ويب ديناميكية وفورية. من خلال فصل منطق جلب البيانات الأولية (مكونات الخادم) عن منطق الاشتراك في الزمن الحقيقي (مكونات العميل) واستخدام إجراءات الخادم للتعديلات الآمنة، يمكنك إنشاء تطبيقات حديثة قابلة للتطوير وعالية الأداء تلبي توقعات المستخدمين اليوم.

HM

Hazem Mohammed

مطور ويب متخصص في هندسة تطبيقات حديثة، سريعة، وقابلة للتوسع.