وضع المعاينة

ملاحظة: تم استبدال هذه الميزة بـ وضع المسودة.

أمثلة

في توثيق الصفحات وتوثيق جلب البيانات، تحدثنا عن كيفية تقديم صفحة مسبقًا في وقت البناء (التوليد الثابت) باستخدام getStaticProps و getStaticPaths.

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

يحتوي Next.js على ميزة تسمى وضع المعاينة التي تحل هذه المشكلة. فيما يلي إرشادات حول كيفية استخدامها.

الخطوة 1: إنشاء مسار API للمعاينة والوصول إليه

ألق نظرة على توثيق مسارات API أولاً إذا لم تكن معتادًا على مسارات API في Next.js.

أولاً، قم بإنشاء مسار API للمعاينة. يمكن أن يكون له أي اسم - على سبيل المثال pages/api/preview.js (أو .ts إذا كنت تستخدم TypeScript).

في مسار API هذا، تحتاج إلى استدعاء setPreviewData على كائن الاستجابة. يجب أن تكون الوسيطة لـ setPreviewData كائنًا، ويمكن استخدامه بواسطة getStaticProps (المزيد عن هذا لاحقًا). في الوقت الحالي، سنستخدم {}.

export default function handler(req, res) {
  // ...
  res.setPreviewData({})
  // ...
}

يضبط res.setPreviewData بعض ملفات تعريف الارتباط في المتصفح والتي تقوم بتشغيل وضع المعاينة. أي طلبات إلى Next.js تحتوي على ملفات تعريف الارتباط هذه سيتم اعتبارها في وضع المعاينة، وسيتغير سلوك الصفحات المولدة بشكل ثابت (المزيد عن هذا لاحقًا).

يمكنك اختبار هذا يدويًا عن طريق إنشاء مسار API مثل أدناه والوصول إليه يدويًا من متصفحك:

pages/api/preview.js
// مثال بسيط لاختباره يدويًا من متصفحك.
export default function handler(req, res) {
  res.setPreviewData({})
  res.end('تم تفعيل وضع المعاينة')
}

إذا فتحت أدوات المطور في متصفحك وزرت /api/preview، ستلاحظ أن ملفات تعريف الارتباط __prerender_bypass و __next_preview_data سيتم تعيينها على هذا الطلب.

الوصول إليه بأمان من نظام إدارة المحتوى الخاص بك

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

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

أولاً، يجب عليك إنشاء سلسلة رمز سرية باستخدام مولد رموز من اختيارك. سيعرف هذا السر فقط تطبيق Next.js الخاص بك ونظام إدارة المحتوى الخاص بك. يمنع هذا السر الأشخاص الذين لا يمكنهم الوصول إلى نظام إدارة المحتوى الخاص بك من الوصول إلى عناوين URL للمعاينة.

ثانيًا، إذا كان نظام إدارة المحتوى الخاص بك يدعم تعيين عناوين URL مخصصة للمعاينة، فحدد ما يلي كعنوان URL للمعاينة. يفترض هذا أن مسار API للمعاينة موجود في pages/api/preview.js.

Terminal
https://<your-site>/api/preview?secret=<token>&slug=<path>
  • <your-site> يجب أن يكون نطاق النشر الخاص بك.
  • <token> يجب استبداله بالرمز السري الذي قمت بإنشائه.
  • <path> يجب أن يكون المسار للصفحة التي تريد معاينتها. إذا كنت تريد معاينة /posts/foo، فيجب عليك استخدام &slug=/posts/foo.

قد يسمح لك نظام إدارة المحتوى الخاص بك بتضمين متغير في عنوان URL للمعاينة بحيث يمكن تعيين <path> ديناميكيًا بناءً على بيانات نظام إدارة المحتوى مثل: &slug=/posts/{entry.fields.slug}

أخيرًا، في مسار API للمعاينة:

  • تحقق من تطابق السر وأن معلمة slug موجودة (إذا لم يكن كذلك، يجب أن يفشل الطلب).
  • استدعِ res.setPreviewData.
  • ثم أعد توجيه المتصفح إلى المسار المحدد بواسطة slug. (يستخدم المثال التالي إعادة توجيه 307).
export default async (req, res) => {
  // تحقق من السر والمعلمات التالية
  // يجب أن يعرف هذا السر فقط مسار API هذا ونظام إدارة المحتوى
  if (req.query.secret !== 'MY_SECRET_TOKEN' || !req.query.slug) {
    return res.status(401).json({ message: 'رمز غير صالح' })
  }

  // جلب نظام إدارة المحتوى للتحقق مما إذا كان `slug` المقدم موجودًا
  // ستنفذ getPostBySlug منطق الجلب المطلوب لنظام إدارة المحتوى
  const post = await getPostBySlug(req.query.slug)

  // إذا لم يكن slug موجودًا، امنع تفعيل وضع المعاينة
  if (!post) {
    return res.status(401).json({ message: 'slug غير صالح' })
  }

  // تفعيل وضع المعاينة عن طريق تعيين ملفات تعريف الارتباط
  res.setPreviewData({})

  // إعادة التوجيه إلى المسار من المنشور الذي تم جلبه
  // لا نعيد التوجيه إلى req.query.slug لأن ذلك قد يؤدي إلى ثغرات إعادة توجيه مفتوحة
  res.redirect(post.slug)
}

إذا نجح ذلك، فسيتم إعادة توجيه المتصفح إلى المسار الذي تريد معاينته مع تعيين ملفات تعريف الارتباط لوضع المعاينة.

الخطوة 2: تحديث getStaticProps

الخطوة التالية هي تحديث getStaticProps لدعم وضع المعاينة.

إذا قمت بطلب صفحة تحتوي على getStaticProps مع تعيين ملفات تعريف الارتباط لوضع المعاينة (عبر res.setPreviewData)، فسيتم استدعاء getStaticProps في وقت الطلب (بدلاً من وقت البناء).

علاوة على ذلك، سيتم استدعاؤها مع كائن context حيث:

  • context.preview سيكون true.
  • context.previewData سيكون هو نفسه الوسيطة المستخدمة لـ setPreviewData.
export async function getStaticProps(context) {
  // إذا طلبت هذه الصفحة مع تعيين ملفات تعريف الارتباط لوضع المعاينة:
  //
  // - سيكون context.preview صحيحًا
  // - سيكون context.previewData هو نفسه
  //   الوسيطة المستخدمة لـ `setPreviewData`.
}

استخدمنا res.setPreviewData({}) في مسار API للمعاينة، لذا سيكون context.previewData هو {}. يمكنك استخدام هذا لتمرير معلومات الجلسة من مسار API للمعاينة إلى getStaticProps إذا لزم الأمر.

إذا كنت تستخدم أيضًا getStaticPaths، فسيكون context.params متاحًا أيضًا.

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

يمكنك تحديث getStaticProps لجلب بيانات مختلفة بناءً على context.preview و/أو context.previewData.

على سبيل المثال، قد يكون لنظام إدارة المحتوى الخاص بك نقطة نهاية API مختلفة للمنشورات المسودة. إذا كان الأمر كذلك، يمكنك استخدام context.preview لتعديل عنوان URL لنقطة نهاية API كما يلي:

export async function getStaticProps(context) {
  // إذا كان context.preview صحيحًا، أضف "/preview" إلى نقطة نهاية API
  // لطلب بيانات المسودة بدلاً من البيانات المنشورة. سيختلف هذا
  // بناءً على نظام إدارة المحتوى الذي تستخدمه.
  const res = await fetch(`https://.../${context.preview ? 'preview' : ''}`)
  // ...
}

هذا كل شيء! إذا قمت بالوصول إلى مسار API للمعاينة (مع secret و slug) من نظام إدارة المحتوى الخاص بك أو يدويًا، يجب أن تكون قادرًا الآن على رؤية محتوى المعاينة. وإذا قمت بتحديث مسودتك دون نشرها، يجب أن تكون قادرًا على معاينة المسودة.

قم بتعيين هذا كعنوان URL للمعاينة على نظام إدارة المحتوى الخاص بك أو قم بالوصول إليه يدويًا، ويجب أن تكون قادرًا على رؤية المعاينة.

Terminal
https://<your-site>/api/preview?secret=<token>&slug=<path>

المزيد من التفاصيل

من الجيد معرفة: أثناء العرض، يعرض next/router علامة isPreview، راجع توثيق كائن الموجه لمزيد من المعلومات.

تحديد مدة وضع المعاينة

يأخذ setPreviewData وسيطة ثانية اختيارية يجب أن تكون كائن خيارات. يقبل المفاتيح التالية:

  • maxAge: يحدد الرقم (بالثواني) لمدة جلسة المعاينة.
  • path: يحدد المسار الذي يجب تطبيق ملف تعريف الارتباط عليه. الافتراضي هو / مما يتيح وضع المعاينة لجميع المسارات.
setPreviewData(data, {
  maxAge: 60 * 60, // تنتهي صلاحية ملفات تعريف الارتباط لوضع المعاينة بعد ساعة واحدة
  path: '/about', // تنطبق ملفات تعريف الارتباط لوضع المعاينة على المسارات مع /about
})

مسح ملفات تعريف الارتباط لوضع المعاينة

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

لمسح ملفات تعريف الارتباط لوضع المعاينة يدويًا، قم بإنشاء مسار API يستدعي clearPreviewData():

pages/api/clear-preview-mode-cookies.js
export default function handler(req, res) {
  res.clearPreviewData({})
}

ثم، أرسل طلبًا إلى /api/clear-preview-mode-cookies لاستدعاء مسار API. إذا كنت تستدعي هذا المسار باستخدام next/link، فيجب عليك تمرير prefetch={false} لمنع استدعاء clearPreviewData أثناء الجلب المسبق للرابط.

إذا تم تحديد مسار في استدعاء setPreviewData، يجب عليك تمرير نفس المسار إلى clearPreviewData:

pages/api/clear-preview-mode-cookies.js
export default function handler(req, res) {
  const { path } = req.query

  res.clearPreviewData({ path })
}

حدود حجم previewData

يمكنك تمرير كائن إلى setPreviewData وجعله متاحًا في getStaticProps. ومع ذلك، نظرًا لأن البيانات سيتم تخزينها في ملف تعريف الارتباط، فهناك قيود على الحجم. حاليًا، بيانات المعاينة محدودة بـ 2 كيلوبايت.

يعمل مع getServerSideProps

يعمل وضع المعاينة أيضًا مع getServerSideProps. سيكون متاحًا أيضًا في كائن context الذي يحتوي على preview و previewData.

من الجيد معرفة: لا يجب عليك تعيين رأس Cache-Control عند استخدام وضع المعاينة لأنه لا يمكن تجاوزه. بدلاً من ذلك، نوصي باستخدام ISR.

يعمل مع مسارات API

سيكون لمسارات API إمكانية الوصول إلى preview و previewData تحت كائن الطلب. على سبيل المثال:

export default function myApiRoute(req, res) {
  const isPreview = req.preview
  const previewData = req.previewData
  // ...
}

فريد لكل next build

تتغير كل من قيمة ملف تعريف الارتباط للتحايل والمفتاح الخاص لتشفير previewData عند اكتمال next build. هذا يضمن أنه لا يمكن تخمين ملف تعريف الارتباط للتحايل.

من الجيد معرفة: لاختبار وضع المعاينة محليًا عبر HTTP، سيحتاج متصفحك إلى السماح بملفات تعريف الارتباط لجهات خارجية والوصول إلى التخزين المحلي.