واجهة التحميل والبث (Streaming)

يساعدك الملف الخاص loading.js في إنشاء واجهة تحميل ذات معنى باستخدام React Suspense. مع هذه الاتفاقية، يمكنك عرض حالة تحميل فورية من الخادم أثناء تحميل محتوى جزء المسار. يتم تبديل المحتوى الجديد تلقائيًا بمجرد اكتمال التصيير.

واجهة التحميل

حالات التحميل الفورية

حالة التحميل الفورية هي واجهة مستخدم احتياطية تُعرض فورًا عند التنقل. يمكنك تصيير مؤشرات تحميل مسبقًا مثل الهياكل العظمية (skeletons) والدوائر الدوارة (spinners)، أو جزء صغير لكن ذو معنى من الشاشات المستقبلية مثل صورة الغلاف، العنوان، إلخ. هذا يساعد المستخدمين على فهم أن التطبيق يستجيب ويوفر تجربة مستخدم أفضل.

قم بإنشاء حالة تحميل عن طريق إضافة ملف loading.js داخل مجلد.

ملف loading.js الخاص
export default function Loading() {
  // يمكنك إضافة أي واجهة مستخدم داخل Loading، بما في ذلك الهيكل العظمي.
  return <LoadingSkeleton />
}
export default function Loading() {
  // يمكنك إضافة أي واجهة مستخدم داخل Loading، بما في ذلك الهيكل العظمي.
  return <LoadingSkeleton />
}

في نفس المجلد، سيتم تداخل loading.js داخل layout.js. سيقوم تلقائيًا بتغليف ملف page.js وأي أطفال أدناه في حدود <Suspense>.

نظرة عامة على loading.js

جيد أن تعرف:

  • التنقل فوري، حتى مع التوجيه المركزي للخادم.
  • التنقل قابل للمقاطعة، مما يعني أن تغيير المسارات لا يحتاج إلى انتظار تحميل محتوى المسار بالكامل قبل التنقل إلى مسار آخر.
  • تبقى التخطيطات المشتركة قابلة للتشغيل أثناء تحميل أجزاء المسار الجديدة.

توصية: استخدم اتفاقية loading.js لأجزاء المسار (التخطيطات والصفحات) حيث يقوم Next.js بتحسين هذه الوظيفة.

البث مع Suspense

بالإضافة إلى loading.js، يمكنك أيضًا إنشاء حدود Suspense يدويًا لمكونات واجهة المستخدم الخاصة بك. يدعم موجه التطبيق البث مع Suspense لكل من بيئات تشغيل Node.js و Edge.

جيد أن تعرف:

  • بعض المتصفحات تقوم بتخزين استجابة البث مؤقتًا. قد لا ترى الاستجابة المبثوثة حتى يتجاوز حجمها 1024 بايت. هذا يؤثر عادةً فقط على تطبيقات "hello world" البسيطة، وليس التطبيقات الحقيقية.

ما هو البث (Streaming)؟

لفهم كيفية عمل البث في React وNext.js، من المفيد فهم التصيير من جانب الخادم (SSR) وقيودها.

مع SSR، هناك سلسلة من الخطوات التي يجب إكمالها قبل أن يتمكن المستخدم من رؤية الصفحة والتفاعل معها:

  1. أولاً، يتم جلب جميع البيانات لصفحة معينة من الخادم.
  2. ثم يقوم الخادم بتصيير HTML للصفحة.
  3. يتم إرسال HTML وCSS وJavaScript للصفحة إلى العميل.
  4. يتم عرض واجهة مستخدم غير تفاعلية باستخدام HTML المُنشأ وCSS.
  5. أخيرًا، يقوم React بترطيب (hydrate) واجهة المستخدم لجعلها تفاعلية.
مخطط يوضح تصيير الخادم بدون بث

هذه الخطوات متسلسلة وحاصرة، مما يعني أن الخادم يمكنه فقط تصيير HTML للصفحة بمجرد جلب جميع البيانات. وعلى العميل، يمكن لـ React فقط ترطيب الواجهة بمجرد تنزيل كود جميع المكونات في الصفحة.

يساعد SSR مع React وNext.js في تحسين أداء التحميل الملاحظ من خلال عرض صفحة غير تفاعلية للمستخدم في أسرع وقت ممكن.

تصيير الخادم بدون بث

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

يسمح لك البث بتقسيم HTML للصفحة إلى أجزاء أصغر وإرسال تلك الأجزاء تدريجيًا من الخادم إلى العميل.

كيف يعمل تصيير الخادم مع البث

هذا يمكّن أجزاء من الصفحة من الظهور عاجلاً، دون انتظار تحميل جميع البيانات قبل تصيير أي واجهة مستخدم.

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

مخطط يوضح تصيير الخادم مع البث

البث مفيد بشكل خاص عندما تريد منع طلبات البيانات الطويلة من حظر تصيير الصفحة حيث يمكنه تقليل وقت أول بايت (TTFB) وأول رسم للمحتوى (FCP). كما أنه يساعد في تحسين الوقت للتفاعل (TTI)، خاصة على الأجهزة الأبطأ.

مثال

يعمل <Suspense> عن طريق تغليف مكون يقوم بإجراء غير متزامن (مثل جلب البيانات)، وعرض واجهة احتياطية (مثل هيكل عظمي، دائرة دوارة) أثناء حدوثه، ثم استبدال مكونك بمجرد اكتمال الإجراء.

import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'

export default function Posts() {
  return (
    <section>
      <Suspense fallback={<p>جاري تحميل التغذية...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>جاري تحميل الطقس...</p>}>
        <Weather />
      </Suspense>
    </section>
  )
}
import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'

export default function Posts() {
  return (
    <section>
      <Suspense fallback={<p>جاري تحميل التغذية...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>جاري تحميل الطقس...</p>}>
        <Weather />
      </Suspense>
    </section>
  )
}
>

باستخدام Suspense، تحصل على فوائد:

1. **تصيير الخادم مع البث** - تصيير HTML تدريجيًا من الخادم إلى العميل.
2. **الترطيب الانتقائي** - يعطي React الأولوية للمكونات التي يجب جعلها تفاعلية أولاً بناءً على تفاعل المستخدم.

لمزيد من أمثلة وحالات استخدام Suspense، يرجى الاطلاع على [توثيق React](https://react.dev/reference/react/Suspense).

### تحسين محركات البحث (SEO)

- سينتظر Next.js اكتمال جلب البيانات داخل [`generateMetadata`](/docs/app/api-reference/functions/generate-metadata) قبل بث الواجهة إلى العميل. هذا يضمن أن الجزء الأول من الاستجابة المبثوثة يتضمن علامات `<head>`.
- نظرًا لأن البث يتم تصييره من الخادم، فهو لا يؤثر على SEO. يمكنك استخدام أداة [Rich Results Test](https://search.google.com/test/rich-results) من Google لمعرفة كيف تظهر صفحتك لمحركات البحث وعرض HTML المُسلسل ([المصدر](https://web.dev/rendering-on-the-web/#seo-considerations)).

### رموز الحالة

عند البث، سيتم إرجاع رمز حالة `200` للإشارة إلى نجاح الطلب.

يمكن للخادم أن يبلغ عن الأخطاء أو المشكلات للعميل داخل المحتوى المبثوث نفسه، على سبيل المثال عند استخدام [`redirect`](/docs/app/api-reference/functions/redirect) أو [`notFound`](/docs/app/api-reference/functions/not-found). نظرًا لأنه تم إرسال رؤوس الاستجابة بالفعل إلى العميل، لا يمكن تحديث رمز حالة الاستجابة. هذا لا يؤثر على SEO.