الفرق بين المراجعتين ل"Next.js/preview mode"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
ط (مراجعة)
سطر 2: سطر 2:
 
<blockquote>'''تنبيه''': تُخصص صفحة التوثيق هذه للنسخة 9.3 من Next.js والنسخ الأعلى.</blockquote>تحدثنا في توثيق [[Next.js/pages|صفحات Next.js]] وتوثيق [[Next.js/data fetching|إحضار البيانات]] عن كيفية تصيير الصفحات مسبقًا أثناء بناء التطبيق (التوليد الساكن Static Generation) باستخدام <code>getStaticProps</code> و <code>getStaticPaths</code>.  
 
<blockquote>'''تنبيه''': تُخصص صفحة التوثيق هذه للنسخة 9.3 من Next.js والنسخ الأعلى.</blockquote>تحدثنا في توثيق [[Next.js/pages|صفحات Next.js]] وتوثيق [[Next.js/data fetching|إحضار البيانات]] عن كيفية تصيير الصفحات مسبقًا أثناء بناء التطبيق (التوليد الساكن Static Generation) باستخدام <code>getStaticProps</code> و <code>getStaticPaths</code>.  
  
تظهر فائدة التوليد الساكن في إحضار البيانات من منظومة إدارة محتوى دون ترويسات headless CMS، لكنه ليس مثاليًا عندما تحاول استعراض مسوّدة عملك مباشرة على الصفحة. فقد ترغب في هذه الحالة في تصيير صفحتك عند الطلب بدل تصييرها أثناء بناء التطبيق، وإحضار المحتوى التجريبي بدلًا من المحتوى الذي سيُنشر. أي قد ترغب بتجاوز التوليد الساكن في هذه الحالة بالتحديد.
+
تظهر فائدة التوليد الساكن في إحضار البيانات من منظومة إدارة محتوى دون واجهة headless CMS، لكنه ليس مثاليًا عندما تضيف مسودة في منظومة إدارة المحتوى تلك دون واجهة وتريد استعراض مسوّدة عملك مباشرة على الصفحة. فقد ترغب في هذه الحالة في تصيير صفحتك عند الطلب بدل تصييرها أثناء بناء التطبيق، وإحضار محتوى المسودة بدلًا من المحتوى المنشور. أي قد ترغب بتجاوز التوليد الساكن في هذه الحالة بالتحديد.
  
تمتلك Next.js ميزة تُدعى نمط الاستعراض لحل هذا الأمر. وإليك طريقة استخدامه.
+
تمتلك Next.js ميزة تُدعى نمط الاستعراض Preview Mode لحل هذا الأمر. وإليك طريقة استخدامه.
  
== الخطوة الأولى: أنشئ مسار API للاستعراض ولج إليه ==
+
== الخطوة الأولى: أنشئ مسار API للاستعراض وانتقل إليه ==
<blockquote>'''تلميح''': الق نظرة أولًا على توثيق [[Next.js/api routes|مسارات API]] إن لم تكن على دراية بها.</blockquote>أنشئ أولًا مسار API لاستعراض الصفحةوسمِّه ما تشاء مثل <code>pages/api/preview.js</code> أو (استخدم الامتداد <code>ts.</code> إن كنت تستخدم TypeScript).  
+
<blockquote>'''تلميح''': الق نظرة أولًا على توثيق [[Next.js/api routes|مسارات API]] إن لم تكن على دراية بها.</blockquote>أنشئ أولًا مسار API لاستعراض الصفحة وسمِّه ما تشاء مثل <code>pages/api/preview.js</code> أو (استخدم الامتداد <code>ts.</code> إن كنت تستخدم [[TypeScript]]).  
  
 
عليك أن تستدعي ضمن هذا المسار الدالة <code>setPreviewData</code> من خلال كائن الاستجابة <code>res</code>، وينبغي أن يكون وسيطها كائنًا قد يُستخدم لاحقًا مع الدالة <code>getStaticProps</code>. أما الآن فسنستخدم القوسين الفارغين <code>{}</code>.<syntaxhighlight lang="javascript">
 
عليك أن تستدعي ضمن هذا المسار الدالة <code>setPreviewData</code> من خلال كائن الاستجابة <code>res</code>، وينبغي أن يكون وسيطها كائنًا قد يُستخدم لاحقًا مع الدالة <code>getStaticProps</code>. أما الآن فسنستخدم القوسين الفارغين <code>{}</code>.<syntaxhighlight lang="javascript">
سطر 27: سطر 27:
 
</syntaxhighlight>قد تلاحظ إن كنت تستخدم أدوات مطوري ويب أن ملفات تعريف ارتباط <code>prerender_bypass__</code> و <code>next_preview_data__</code> ستُهيئ عند إرسال هذا الطلب.
 
</syntaxhighlight>قد تلاحظ إن كنت تستخدم أدوات مطوري ويب أن ملفات تعريف ارتباط <code>prerender_bypass__</code> و <code>next_preview_data__</code> ستُهيئ عند إرسال هذا الطلب.
  
=== الولوج الآمن إلى الصفحة من منظومة إدارة محتوى دون ترويسة ===
+
=== الولوج الآمن إلى الصفحة من منظومة إدارة محتوى دون واجهة ===
 
قد ترغب عمليًا باستدعاء مسار API بشكل آمن من منظومة إدارة محتوى CMS، وستختلف خطوات إنجاز الأمر وفقًا للمنظومة التي تستخدمها. لهذا سنستعرض بعض الخطوات الشائعة التي يمكنك اتخاذها. تفترض هذه الخطوات أن المنظومة التي تستخدمها تدعم ضبط عناوين URL مخصصة للاستعراض، فإن لم تكن كذلك، ستبقى قادرًا على استخدام هذه الطريقة لتأمين عناوين الاستعراض، لكن عليك أن تبني وتلج إلى هذه العناوين يدويًا.
 
قد ترغب عمليًا باستدعاء مسار API بشكل آمن من منظومة إدارة محتوى CMS، وستختلف خطوات إنجاز الأمر وفقًا للمنظومة التي تستخدمها. لهذا سنستعرض بعض الخطوات الشائعة التي يمكنك اتخاذها. تفترض هذه الخطوات أن المنظومة التي تستخدمها تدعم ضبط عناوين URL مخصصة للاستعراض، فإن لم تكن كذلك، ستبقى قادرًا على استخدام هذه الطريقة لتأمين عناوين الاستعراض، لكن عليك أن تبني وتلج إلى هذه العناوين يدويًا.
  
* أولًا، عليك إنشاء مفتاح استيثاق نصي سري مستخدمًا موّلد مفاتيح استيثاق token تختاره، وسيعرفه فقط تطبيق Next.js والمنظومة. وهكذا لن يتمكن الأشخاص الذين لا يُسمح لهم بدخول المنظومة من الوصول إلى عناوين URL.
+
أولًا، عليك إنشاء مفتاح استيثاق نصي سري مستخدمًا موّلد مفاتيح استيثاق token تختاره، وسيعرفه فقط تطبيق Next.js والمنظومة. وهكذا لن يتمكن الأشخاص الذين لا يُسمح لهم بدخول المنظومة من الوصول إلى عناوين URL.
* ثانيًا، إن كانت تدعم منظومة إدارة المحتوى التي لا تستخدم الترويسات ضبط عناوين استعراض مخصصة، حدد العنوان التالي كعنوان URL للاستعراض (على افتراض أن وجهة مسار API هي <code>pages/api/preview.js</code>).  
+
 
<syntaxhighlight lang="bash">
+
ثانيًا، إن كانت تدعم منظومة إدارة المحتوى التي لا تستخدم الترويسات ضبط عناوين استعراض مخصصة، حدد العنوان التالي كعنوان URL للاستعراض (على افتراض أن وجهة مسار API هي <code>pages/api/preview.js</code>).<syntaxhighlight lang="bash">
 
https://<your-site>/api/preview?secret=<token>&slug=<path>
 
https://<your-site>/api/preview?secret=<token>&slug=<path>
</syntaxhighlight>
+
</syntaxhighlight>يتألف من الأقسام التالية:
  
# <code><your-site></code>: اسم نطاق التطوير الخاص بك.
+
* <code><your-site></code>: اسم نطاق التطوير الخاص بك.
# <code><token></code>: يُستبدل بمفتاح الاستيثاق الذي ولّدته.
+
* <code><token></code>: يُستبدل بمفتاح الاستيثاق الذي ولّدته.
# <code><path></code>: مسار الصفحة التي تريد استعراضها. فإن أردت استعراض الصفحة <code>posts/foo/</code> مثلًا، عليك أن تستخدم <code>slug=/posts/foo&</code>. وقد تسمح لك المنظومة بأن تضع متغيرًا في عنوان الاستعراض، وبالتالي يمكن أن يُضبط المسار <code><path></code> ديناميكيًا وفقًا لبيانات المنظومة كالتالي: <code>slug=/posts/{entry.fields.slug}&</code>.
+
* <code><path></code>: مسار الصفحة التي تريد استعراضها. فإن أردت استعراض الصفحة <code>posts/foo/</code> مثلًا، عليك أن تستخدم <code>slug=/posts/foo&</code>. وقد تسمح لك المنظومة بأن تضع متغيرًا في عنوان الاستعراض، وبالتالي يمكن أن يُضبط المسار <code><path></code> ديناميكيًا وفقًا لبيانات المنظومة كالتالي: <code>slug=/posts/{entry.fields.slug}&</code>.
  
* أخيرًا، نفّذ ما يلي في مسار API الخاص بالاستعراض:
+
أخيرًا، نفّذ ما يلي في مسار API الخاص بالاستعراض:
** تأكد من تطابق مفتاح الاستيثاق، وأن معاملات <code>slug</code> موجودة (ينبغي أن يخفق الطلب إن لم تكن موجودة).
+
* تأكد من تطابق مفتاح الاستيثاق، وأن معاملات <code>slug</code> موجودة (ينبغي أن يخفق الطلب إن لم تكن موجودة).
** استدع الدالة <code>res.setPreviewData</code>.
+
* استدع الدالة <code>res.setPreviewData</code>.
** وجّه المتصفح إلى المسار المحدد في <code><path></code> (يستخدم المثال التالي التوجيه 307 (إعادة توجيه مؤقت)).
+
* وجّه المتصفح إلى المسار المحدد في <code><path></code> (يستخدم المثال التالي التوجيه 307 إعادة توجيه مؤقت).
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
export default async (req, res) => {
 
export default async (req, res) => {
سطر 53: سطر 53:
  
 
   //`slug` تأكد من وجود معاملات  
 
   //`slug` تأكد من وجود معاملات  
   //منطق إحضارات البيانات من المنظومة getPostBySlug ستنجز الدالة  
+
   // CMS منطق إحضارات البيانات من منظومة getPostBySlug ستنجز الدالة  
 
   const post = await getPostBySlug(req.query.slug)
 
   const post = await getPostBySlug(req.query.slug)
  
سطر 88: سطر 88:
  
 
=== إحضار بيانات الاستعراض ===
 
=== إحضار بيانات الاستعراض ===
يمكنك تحديث <code>getStaticProps</code> لإحضار البيانات المختلفة وفقًا للخاصية <code>context.preview</code> أو/و <code>context.previewData</code>. فقد تمتلك منظومة إدارة المحتوى لديك على سبيل المثال وصلات API مختلفة لمسودات المنشورات، وبالتالي ستتمكن حينها من استخدام <code>context.preview</code> لتعديل عنوان URL لوصلة API كما يلي:<syntaxhighlight lang="javascript">
+
يمكنك تحديث <code>getStaticProps</code> لإحضار البيانات المختلفة وفقًا للخاصية <code>context.preview</code> أو/و <code>context.previewData</code>. فقد تمتلك منظومة إدارة المحتوى CMS لديك على سبيل المثال وصلات API مختلفة لمسودات المنشورات، وبالتالي ستتمكن حينها من استخدام <code>context.preview</code> لتعديل عنوان URL لوصلة API كما يلي:<syntaxhighlight lang="javascript">
 
export async function getStaticProps(context) {
 
export async function getStaticProps(context) {
 
   // API إلى وصلة "/preview" محققًا اربط context.preview إن كان  
 
   // API إلى وصلة "/preview" محققًا اربط context.preview إن كان  
سطر 96: سطر 96:
 
   // ...
 
   // ...
 
}
 
}
</syntaxhighlight>فإن ولجت الآن إلى مسار API باستخدام <code>secret</code> و <code>slug</code> من خلال منظومة إدارة محتوى دون ترويسات أو يدويًا، من المفترض أن ترى المحتوى الذي تنوي استعراضه. وإن حدَّثت مسودتك دون أن تنشرها، من المفترض أن تكون قادرًا على استعراضها أيضًا:<syntaxhighlight lang="bash">
+
</syntaxhighlight>فإن ولجت الآن إلى مسار API باستخدام <code>secret</code> و <code>slug</code> من خلال منظومة إدارة محتوى دون واجهة headless CMS أو يدويًا، من المفترض أن ترى المحتوى الذي تنوي استعراضه. وإن حدَّثت مسودتك دون أن تنشرها، من المفترض أن تكون قادرًا على استعراضها أيضًا:<syntaxhighlight lang="bash">
 
# للاستعراض URL يضبط ما يلي عنوان
 
# للاستعراض URL يضبط ما يلي عنوان
 
# من خلال منظومة إدارة محتوى أو يدويًا وستكون قادرًا على استعراض المحتوى
 
# من خلال منظومة إدارة محتوى أو يدويًا وستكون قادرًا على استعراض المحتوى
سطر 104: سطر 104:
 
== تفاصيل أكثر عن نمط الاستعراض في Next.js ==
 
== تفاصيل أكثر عن نمط الاستعراض في Next.js ==
 
إليك بعض التفاصيل الهامة التي تتعلق بنمط الاستعراض.
 
إليك بعض التفاصيل الهامة التي تتعلق بنمط الاستعراض.
 +
 +
'''ملاحظة''': أثناء التصيير يوفر <code>next/router</code> الراية <code>isPreview</code>، وارجع إلى قسم [[Next.js/next router#.D8.A7.D9.84.D9.83.D8.A7.D8.A6.D9.86 router .D9.81.D9.8A Next.js|الكائن router]] لمزيد من التفاصيل.
  
 
=== حذف ملفات تعريف ارتباط نمط الاستعراض ===
 
=== حذف ملفات تعريف ارتباط نمط الاستعراض ===
سطر 120: سطر 122:
  
 
* <code>maxAge</code>: يحدد عدد الثواني التي ينبغي أن تدومها جلسة العمل.
 
* <code>maxAge</code>: يحدد عدد الثواني التي ينبغي أن تدومها جلسة العمل.
 +
* path: يحدد المسار الذي يجب لملفات تعريف الارتباط أن ترتبط به، وقيمته الافتراضية / الذي يفعل وضع الاستعراض لكل المسارات.
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
setPreviewData(data, {
 
setPreviewData(data, {
 
   maxAge: 60 * 60, //تبقى ملفات تعريف الارتباط الخاصة بالاستعراض ساعة
 
   maxAge: 60 * 60, //تبقى ملفات تعريف الارتباط الخاصة بالاستعراض ساعة
 +
  path: '/about', // فقط /about تطبق ملفات تعريف الارتباط لوضع الاستعراض مع مسار
 
})
 
})
 
</syntaxhighlight>
 
</syntaxhighlight>
سطر 130: سطر 134:
  
 
=== العمل مع الدالة <code>getServerSideProps</code> ===
 
=== العمل مع الدالة <code>getServerSideProps</code> ===
يعمل نمط الاستعراض مع الدالة <code>getServerSideProps</code> أيضًا، وسيكون متاحًا مع الكائن الذي يضم <code>preview</code> و <code>previewData</code>.
+
يعمل نمط الاستعراض مع الدالة <code>getServerSideProps</code> أيضًا، وسيكون متاحًا مع الكائن <code>context</code> الذي يضم <code>preview</code> و <code>previewData</code>.
  
 
=== العمل مع مسارات API ===
 
=== العمل مع مسارات API ===
يمكن لمسارات API الوصول إلى قيم <code>preview</code> و <code>previewData</code> ضمن الكائن الذي يُطلب. إليك مثالًا:<syntaxhighlight lang="javascript">
+
يمكن لمسارات API الوصول إلى قيم <code>preview</code> و <code>previewData</code> ضمن كائن الطلب <code>req</code>. إليك مثالًا:<syntaxhighlight lang="javascript">
 
export default function myApiRoute(req, res) {
 
export default function myApiRoute(req, res) {
 
   const isPreview = req.preview
 
   const isPreview = req.preview
سطر 143: سطر 147:
 
=== مفاتيح وملفات ارتباط خاصة لكل عملية بناء <code>next build</code> ===
 
=== مفاتيح وملفات ارتباط خاصة لكل عملية بناء <code>next build</code> ===
 
تتغير قيم ملفات تعريف الارتباط التي تفرض حالة الاستعراض ومفتاح الاستيثاق لتشفير بيانات <code>previewData</code> مع اكتمال كل عملية بناء <code>next build</code>. يضمن ذلك عدم القدرة على تخمين قيم ملفات تعريف الارتباط.<blockquote>'''ملاحظة''': عليك أن تسمح باستخدام ملفات تعريف ارتباط مصدرها طرف آخر وإذنًا بالوصول إلى التخزين المحلي، لاختبار نمط الاستعراض محليًا ضمن متصفحك عبر طلبات HTTP.</blockquote>
 
تتغير قيم ملفات تعريف الارتباط التي تفرض حالة الاستعراض ومفتاح الاستيثاق لتشفير بيانات <code>previewData</code> مع اكتمال كل عملية بناء <code>next build</code>. يضمن ذلك عدم القدرة على تخمين قيم ملفات تعريف الارتباط.<blockquote>'''ملاحظة''': عليك أن تسمح باستخدام ملفات تعريف ارتباط مصدرها طرف آخر وإذنًا بالوصول إلى التخزين المحلي، لاختبار نمط الاستعراض محليًا ضمن متصفحك عبر طلبات HTTP.</blockquote>
 +
 +
== أمثلة ==
 +
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-wordpress WordPress Example] ([https://next-blog-wordpress.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-datocms DatoCMS Example] ([https://next-blog-datocms.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-takeshape TakeShape Example] ([https://next-blog-takeshape.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-sanity Sanity Example] ([https://next-blog-sanity.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-prismic Prismic Example] ([https://next-blog-prismic.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-contentful Contentful Example] ([https://next-blog-contentful.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-strapi Strapi Example] ([https://next-blog-strapi.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-prepr Prepr Example] ([https://next-blog-prepr.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-agilitycms Agility CMS Example] ([https://next-blog-agilitycms.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-cosmic Cosmic Example] ([https://next-blog-cosmic.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-buttercms ButterCMS Example] ([https://next-blog-buttercms.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-storyblok Storyblok Example] ([https://next-blog-storyblok.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-graphcms GraphCMS Example] ([https://next-blog-graphcms.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-kontent Kontent Example] ([https://next-blog-kontent.vercel.app// تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-umbraco-heartcore Umbraco Heartcore Example] ([https://next-blog-umbraco-heartcore.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-plasmic Plasmic Example] ([https://nextjs-plasmic-example.vercel.app/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-enterspeed Enterspeed Example] ([https://next-blog-demo.enterspeed.com/ تجربة حية])
 +
* [https://github.com/vercel/next.js/tree/canary/examples/cms-makeswift Makeswift Example] ([https://nextjs-makeswift-example.vercel.app/ تجربة حية])
  
 
== اقرأ أيضًا ==
 
== اقرأ أيضًا ==

مراجعة 06:49، 25 ديسمبر 2022

تنبيه: تُخصص صفحة التوثيق هذه للنسخة 9.3 من Next.js والنسخ الأعلى.

تحدثنا في توثيق صفحات Next.js وتوثيق إحضار البيانات عن كيفية تصيير الصفحات مسبقًا أثناء بناء التطبيق (التوليد الساكن Static Generation) باستخدام getStaticProps و getStaticPaths.

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

تمتلك Next.js ميزة تُدعى نمط الاستعراض Preview Mode لحل هذا الأمر. وإليك طريقة استخدامه.

الخطوة الأولى: أنشئ مسار API للاستعراض وانتقل إليه

تلميح: الق نظرة أولًا على توثيق مسارات API إن لم تكن على دراية بها.

أنشئ أولًا مسار API لاستعراض الصفحة وسمِّه ما تشاء مثل pages/api/preview.js أو (استخدم الامتداد ts. إن كنت تستخدم TypeScript). عليك أن تستدعي ضمن هذا المسار الدالة setPreviewData من خلال كائن الاستجابة res، وينبغي أن يكون وسيطها كائنًا قد يُستخدم لاحقًا مع الدالة getStaticProps. أما الآن فسنستخدم القوسين الفارغين {}.

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

تهيئ الدالة res.setPreviewData بعض ملفات تعريف الارتباط cookies في المتصفح والتي تفعّل نمط الاستعراض. تُعد أية طلبات تتضمن ملفات تعريف الارتباط تلك ضمن نمط الاستعراض، ويتغير سلوك التوليد الساكن للصفحات. بإمكانك اختبار الأمر يدويًا، بإنشاء مسار API كما في المثال التالي والولوج إليه من خلال المتصفح:

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

قد تلاحظ إن كنت تستخدم أدوات مطوري ويب أن ملفات تعريف ارتباط prerender_bypass__ و next_preview_data__ ستُهيئ عند إرسال هذا الطلب.

الولوج الآمن إلى الصفحة من منظومة إدارة محتوى دون واجهة

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

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

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

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

يتألف من الأقسام التالية:

  • <your-site>: اسم نطاق التطوير الخاص بك.
  • <token>: يُستبدل بمفتاح الاستيثاق الذي ولّدته.
  • <path>: مسار الصفحة التي تريد استعراضها. فإن أردت استعراض الصفحة posts/foo/ مثلًا، عليك أن تستخدم slug=/posts/foo&. وقد تسمح لك المنظومة بأن تضع متغيرًا في عنوان الاستعراض، وبالتالي يمكن أن يُضبط المسار <path> ديناميكيًا وفقًا لبيانات المنظومة كالتالي: slug=/posts/{entry.fields.slug}&.

أخيرًا، نفّذ ما يلي في مسار API الخاص بالاستعراض:

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

  //`slug` تأكد من وجود معاملات 
  // CMS منطق إحضارات البيانات من منظومة getPostBySlug ستنجز الدالة 
  const post = await getPostBySlug(req.query.slug)

  //موجودة `slug` لا تمكّن نمط الاستعراض ما لم تكن 
  if (!post) {
    return res.status(401).json({ message: 'Invalid slug' })
  }

  // مكّن نمط الاستعراض من خلال ضبط ملفات تعريف الارتباط
  res.setPreviewData({})

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

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

الخطوة الثانية: حدّث قيم الخاصيات باستخدام 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 عند الحاجة. وسيكون context.params متاحًا إيضًا إن كنت تستخدم getStaticPaths.

إحضار بيانات الاستعراض

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

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

فإن ولجت الآن إلى مسار API باستخدام secret و slug من خلال منظومة إدارة محتوى دون واجهة headless CMS أو يدويًا، من المفترض أن ترى المحتوى الذي تنوي استعراضه. وإن حدَّثت مسودتك دون أن تنشرها، من المفترض أن تكون قادرًا على استعراضها أيضًا:

# للاستعراض URL يضبط ما يلي عنوان
# من خلال منظومة إدارة محتوى أو يدويًا وستكون قادرًا على استعراض المحتوى
https://<your-site>/api/preview?secret=<token>&slug=<path>

تفاصيل أكثر عن نمط الاستعراض في Next.js

إليك بعض التفاصيل الهامة التي تتعلق بنمط الاستعراض.

ملاحظة: أثناء التصيير يوفر next/router الراية isPreview، وارجع إلى قسم الكائن router لمزيد من التفاصيل.

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

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

لإزالة ملفات تعريف الارتباط لنمط الاستعراض يدويًا، أنشئ مسار 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 معاملًا اختياريًا ثانيًا يُفترض أن يكون كائن خيارات. يقبل هذا الكائن المفاتيح التالية:

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

حدود حجم بيانات الاستعراض previewData

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

العمل مع الدالة getServerSideProps

يعمل نمط الاستعراض مع الدالة getServerSideProps أيضًا، وسيكون متاحًا مع الكائن context الذي يضم preview و previewData.

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

يمكن لمسارات API الوصول إلى قيم preview و previewData ضمن كائن الطلب req. إليك مثالًا:

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

مفاتيح وملفات ارتباط خاصة لكل عملية بناء next build

تتغير قيم ملفات تعريف الارتباط التي تفرض حالة الاستعراض ومفتاح الاستيثاق لتشفير بيانات previewData مع اكتمال كل عملية بناء next build. يضمن ذلك عدم القدرة على تخمين قيم ملفات تعريف الارتباط.

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

أمثلة

اقرأ أيضًا

المصادر

  • الصفحة Preview Mode من توثيق Next.js الرسمي.