الفرق بين المراجعتين لصفحة: «Next.js/pages»

من موسوعة حسوب
لا ملخص تعديل
طلا ملخص تعديل
 
(5 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:الصفحات في Next.js}}</noinclude>
<noinclude>{{DISPLAYTITLE:الصفحات في Next.js}}</noinclude><blockquote>
الصفحة هي [[React/react component|مكوّن رياكت]] مصدر عن ملفات موجودة في المجلد <code>pages</code> وتمتلك إحدى الامتدادات التالية: <code>js.</code> أو <code>jsx.</code> أو <code>ts.</code> أو <code>tsx.</code>. تقترن كل صفحة بمسار يتعلق باسم الملف، فلو أنشأت على سبيل المثال الملف <code>pages/about.js</code> الذي يصّدر مكوّن رياكت التالي، ستتمكن من الوصول إليه من خلال العنوان <code>/about</code>.<syntaxhighlight>
'''ملاحظة''': نوفر دعمًا لعملية [[Next.js/Routing|توجيه مُحسَّنة للمسارات]] في Next.js، واقرأ تدوينة [https://nextjs.org/blog/layouts-rfc Layouts RFC] لمزيد من التفاصيل.</blockquote>
الصفحة page هي [[React/react component|مكوّن React]] مصدر عن ملفات موجودة في المجلد <code>pages</code> وتمتلك إحدى الامتدادات التالية: <code>js.</code> أو <code>jsx.</code> أو <code>ts.</code> أو <code>tsx.</code>. تقترن كل صفحة بمسار يتعلق باسم الملف، فلو أنشأت على سبيل المثال الملف <code>pages/about.js</code> الذي يصدّر مكوّن React التالي، ستتمكن من الوصول إليه من خلال المسار ‎<code>/about</code>.<syntaxhighlight lang="javascript">
function About() {
function About() {
   return <div>About</div>
   return <div>About</div>
سطر 6: سطر 7:


export default About
export default About
</syntaxhighlight><blockquote>صفحات بمسارات ديناميكية: تدعم [[Next.js/routing|المسارات الديناميكية للصفحات]]. فإن انشأت الملف <code>pages/posts/[id].js</code> مثلًا، أمكنك الوصول إليه بكتابة العنوان <code>posts/1</code> أو <code>posts/2</code> وهكذا.</blockquote>
</syntaxhighlight>
 
== صفحات بمسارات ديناميكية في Next.js ==
تدعم [[Next.js/Routing#.D8.A7.D9.84.D9.88.D8.AC.D9.87.D8.A7.D8.AA .D8.A7.D9.84.D8.AF.D9.8A.D9.86.D8.A7.D9.85.D9.8A.D9.83.D9.8A.D8.A9 .D9.81.D9.8A Next.js|المسارات الديناميكية للصفحات]]. فإن انشأت الملف <code>pages/posts/[id].js</code> مثلًا، أمكنك الوصول إليه بكتابة المسار <code>posts/1</code> أو <code>posts/2</code> وهكذا.


== التصيير المسبق للصفحات ==
== التصيير المسبق للصفحات في Next.js ==
تصيّر Next.js الصفحات مسبقًا pre-render، ويعني ذلك توليد شيفرة [[HTML]] لكل صفحة مسبقًا بدلًا من إلقاء الحمل كاملًا على محّرك جافا سكربت الذي يعمل من طرف العميل. وقد يُحسّن هذا الأمر الأداء، كما يُحسن ترتيب ظهور الصفحة في محرّكات البحث SEO (سيو أفضل).
تصيّر Next.js الصفحات مسبقًا pre-render، ويعني ذلك توليد شيفرة [[HTML]] لكل صفحة مسبقًا بدلًا من إلقاء الحمل كاملًا على محرّك [[JavaScript]] الذي يعمل من طرف العميل. وقد يُحسّن هذا الأمر الأداء، كما يُحسن ترتيب ظهور الصفحة في محرّكات البحث SEO (سيو أفضل).


تُزوَّد شيفرة HTML المولَّدة لكل صفحة بحد أدنى من شيفرة جافا سكربت الضرورية لعملها. وعندما يُحمّل المتصفح الصفحة، ستُنفَّذ شيفرة جافا سكربت لتمنح الصفحة تفاعلية أكبر (تُدعى هذه العملية بالترطيب hydration).
تُزوَد شيفرة HTML المولَّدة لكل صفحة بحد أدنى من شيفرة JavaScript الضرورية لعملها. وعندما يُحمّل المتصفح الصفحة، ستُنفَّذ شيفرة JavaScript لتمنح الصفحة تفاعلية أكبر (تُدعى هذه العملية بالترطيب hydration).


=== نمطي التصيير المسبق ===
=== نمطي التصيير المسبق ===
للتصيير المسبق في Next.js نمطين هما: التوليد الساكن Static Generation والتصيير من جانب الخادم Server-side Rendering ويقتصر الفارق بينهما على اللحظة التي توّّلد فيها شيفرة HTML.
للتصيير المسبق في Next.js نمطين هما: التوليد الساكن Static Generation والتصيير من جانب الخادم Server-side Rendering ويقتصر الفارق بينهما على اللحظة التي تولّد فيها شيفرة HTML.


* '''التوليد الساكن (مُستحسن)''': توّلد شيفرة HTML وفق هذا النمط أثناء بناء الصفحة ويُعاد استخدامها عند كل طلب.
* '''التوليد الساكن (مُستحسن)''': تولّد شيفرة HTML وفق هذا النمط أثناء بناء الصفحة ويُعاد استخدامها عند كل طلب.
* ا'''لتصيير من جانب الخادم''': توّلد شيفرة HTML عند كل طلب.
* ا'''لتصيير من جانب الخادم''': تولّد شيفرة HTML عند كل طلب.


تمنحك Next.js القدرة على اختيار نمط التصيير المسبق لكل صفحة، وبالتالي ستتمكن من بناء تطبيقات هجينة عندما تستخدم التوليد الساكن لمعظم صفحاته وتجعل تصيير بعضها الآخر من جانب الخادم.
تمنحك Next.js القدرة على اختيار نمط التصيير المسبق لكل صفحة، وبالتالي ستتمكن من بناء تطبيقات هجينة عندما تستخدم التوليد الساكن لمعظم صفحاته وتجعل تصيير بعضها الآخر من جانب الخادم.


ننصح باستخدام التوليد الساكن للشيفرة مقابل التصيير من جانب الخادم لأسباب تتعلق بالأداء. إذ يمكن أن تخزّن الصفحات الموّلدة بالنمط الساكن في شبكات توزيع المحتوى CDN دون أي إعدادات إضافية مما يعزز الأداء. لكن قد تجد أن التصيير من جانب الخادم هو الخيار الوحيد في بعض الحالات.
ننصح باستخدام التوليد الساكن للشيفرة مقابل التصيير من جانب الخادم لأسباب تتعلق بالأداء، إذ يمكن أن تخزّن الصفحات المولّدة بالنمط الساكن في [https://academy.hsoub.com/devops/networking/%D8%B4%D8%A8%D9%83%D8%A7%D8%AA-%D8%AA%D9%88%D8%B2%D9%8A%D8%B9-%D8%A7%D9%84%D9%85%D8%AD%D8%AA%D9%88%D9%89-content-distribution-networks-r569/ شبكات توزيع المحتوى CDN] دون أي إعدادات إضافية مما يعزز الأداء، لكن قد تجد أنّ التصيير من جانب الخادم هو الخيار الوحيد في بعض الحالات.


بالإمكان أيضًا استخدام التصيير من جانب العميل Client-side Rendering جنبًا إلى جنب مع التوليد الساكن أو التصيير من جانب الخادم، أي أنه بالإمكان تصيير جزء من الصفحة كليًا بواسطة جافا سكربت منفَّذة من ناحية العميل. لمزيد من المعلومات راجع [[Next.js/data fetching|توثيق إحضار البيانات]].
بالإمكان أيضًا استخدام التصيير من جانب العميل Client-side Rendering جنبًا إلى جنب مع التوليد الساكن أو التصيير من جانب الخادم، أي أنه بالإمكان تصيير جزء من الصفحة كليًا بواسطة JavaScript منفَّذة من طرف العميل، ولمزيد من المعلومات راجع [[Next.js/data fetching|توثيق إحضار البيانات]].


== التوليد الساكن للشيفرة في Next.js ==
== التوليد الساكن للشيفرة في Next.js ==
توّلد شيفرة HTML عند استخدام نمط التوليد الساكن أثناء بناء التطبيق. ويعني ذلك من منظور مرحلة الإنتاج أن توليد HTML يجري عند تنفيذ الأمر <code>next build</code>. تُستخدم بعد ذلك هذه الشيفرة مع كل طلب، ويمكن تخزينها مؤقتًا ضمن شبكة توصيل المحتوى.
تولّد شيفرة HTML عند استخدام نمط التوليد الساكن أثناء بناء التطبيق. ويعني ذلك من منظور مرحلة الإنتاج أنّ توليد HTML يجري عند تنفيذ الأمر <code>next build</code>. تُستخدم بعد ذلك هذه الشيفرة مع كل طلب، ويمكن تخزينها مؤقتًا ضمن شبكة توصيل المحتوى CDN، وبالإمكان توليد صفحات تحوي بيانات في Next.js أو لا، لنلق نظرة على ذلك.
 
بالإمكان توليد صفحات تحوي بيانات في Next.js أو لا تحتوي بيانات، لنلق نظرة على ذلك.


=== التوليد الساكن لصفحات بلا بيانات في Next.js ===
=== التوليد الساكن لصفحات بلا بيانات ===
تصيّر Next.js الصفحات مسبقًا وفق نمط التوليد الساكن افتراضيًا، وإليك مثالًا:<syntaxhighlight>
تصيّر Next.js الصفحات مسبقًا وفق نمط التوليد الساكن افتراضيًا، وإليك مثالًا:<syntaxhighlight lang="javascript">
function About() {
function About() {
   return <div>About</div>
   return <div>About</div>
سطر 37: سطر 39:


export default About
export default About
</syntaxhighlight>
</syntaxhighlight>لاحظ أن هذه الصفحة ليست بحاجة إلى جلب أي بيانات من أي مصدر خارجي لعرضها، وبذلك تولد Next.js صفحة HTML ساكنة ثابتة لا تتغير أثناء عملية البناء.


=== التوليد الساكن لصفحات تحتوي بيانات في Next.js ===
=== التوليد الساكن لصفحات تحتوي بيانات ===
قد تحتاج بعض الصفحات إلى بيانات خارجية لإتمام التصيير المسبق لها. سيصادفنا في حالات كهذه سناريوهان يمكن تطبيق أحدهما أو كلاهما، ويمكن عندها استخدام الدوال التالية التي تقدمها Next.js:
قد تحتاج بعض الصفحات إلى بيانات خارجية لإتمام التصيير المسبق لها. سيصادفنا في حالات كهذه وضعان يمكن تطبيق أحدهما أو كلاهما، ويمكن عندها استخدام الدوال التالية التي تقدمها Next.js:


# <code>getStaticProps</code>: وتُسخدم عندما يعتمد محتوى صفحتك على بيانات خارجية.
# <code>getStaticProps</code>: وتُسخدم عندما يعتمد محتوى صفحتك على بيانات خارجية.
# <code>getStaticPaths</code>: وتُستخدم عندما تعتمد المسارات في الصفحة على بيانات خارجية، وعادة ما تُستخدم إلى جانب الدالة <code>getStaticProps</code>.
# <code>getStaticPaths</code>: وتُستخدم عندما تعتمد المسارات paths في الصفحة على بيانات خارجية، وعادة ما تُستخدم إلى جانب الدالة <code>getStaticProps</code>.


==== السيناريو الأول: اعتماد الصفحة على بيانات خارجية ====
==== الحالة الأولى: اعتماد الصفحة على بيانات خارجية ====
وكمثال على ذلك مدوّنة قد تحتاج إلى إحضار قائمة بالمنشورات من نظام إدارة المحتوى content management system:<syntaxhighlight>
وكمثال على ذلك مدوّنة قد تحتاج إلى إحضار قائمة بالمنشورات من نظام إدارة المحتوى content management system:<syntaxhighlight lang="javascript">
// TODO: Need to fetch `posts` (by calling some API endpoint)
// (عليك إحضار المنشورات (باستدعاء وصلة برمجية خارجية
//       before this page can be pre-rendered.
// قبل أن تُصيَّر هذه الصفحة مسبقًا
function Blog({ posts }) {
function Blog({ posts }) {
   return (
   return (
سطر 61: سطر 63:
export default Blog
export default Blog
</syntaxhighlight>
</syntaxhighlight>
تسمح لك Next.js أن تصدّر دالة غير متزامنة تُدعى <code>getStaticProps</code> من الملف ذاته إن أردت إحضار تلك البيانات في مرحلة التصيير المسبق. تُستدعى هذ الدالة أثناء بناء التطبيق وتسمح لك بتمرير البيانات المُحضرة إل خاصيات الصفحة <code>props</code> في مرحلة التصيير المسبق.<syntaxhighlight>
تسمح لك Next.js أن تصدّر دالة غير متزامنة تُدعى <code>getStaticProps</code> من الملف ذاته إن أردت إحضار تلك البيانات في مرحلة التصيير المسبق، وتُستدعى هذ الدالة أثناء بناء التطبيق وتسمح لك بتمرير البيانات المُحضرة إلى خاصيات الصفحة <code>props</code> في مرحلة التصيير المسبق.<syntaxhighlight lang="javascript">
function Blog({ posts }) {
function Blog({ posts }) {
   //posts يُصيّر ...
   // عرض المنشورات ...
}
}


سطر 71: سطر 73:
   const res = await fetch('https://.../posts')
   const res = await fetch('https://.../posts')
   const posts = await res.json()
   const posts = await res.json()
   // المنشورات كخاصيات أثناء بناء التطبيقBlog يتلقى المكوّن  
   // المنشورات كخاصيات أثناء بناء التطبيق Blog يتلقى المكوّن  
   //{ props: { posts } }بإعادة
   //{ props: { posts } }بإعادة
   return {
   return {
سطر 81: سطر 83:


export default Blog
export default Blog
</syntaxhighlight>راجع [[Next.js/data fetching|توثيق إحضار البيانات]] لتطلع أكثر على عمل الدالة <code>getStaticProps</code>.  
</syntaxhighlight>راجع [[Next.js/data fetching|توثيق إحضار البيانات]] لتطلع أكثر على عمل الدالة <code>[[Next.js/data fetching#.D8.A7.D9.84.D8.AA.D9.88.D9.84.D9.8A.D8.AF .D8.A7.D9.84.D8.B3.D8.A7.D9.83.D9.86 .D9.84.D9.84.D8.B5.D9.81.D8.AD.D8.A7.D8.AA .D9.81.D9.8A Next.js .D8.A8.D8.A7.D8.B3.D8.AA.D8.AE.D8.AF.D8.A7.D9.85 .D8.A7.D9.84.D8.AF.D8.A7.D9.84.D8.A9 getStaticProps|getStaticProps]]</code>.  


==== السناريو الثاني: اعتماد مسارات الصفحة على بيانات خارجية ====
==== الحالة الثانية: اعتماد مسارات الصفحة على بيانات خارجية ====
تتيح لك Next.js أن تنشئ صفحات تعتمد المسارت الديناميكية. إذ تستطيع مثلًا إنشاء ملف يُدعى <code>pages/posts/[id].js</code> لاستعراض منشور مفرد من مدونة وفقًا للمعرِّف الفريد الخاص به <code>id</code>، وسيعرض لك المسار <code>posts/1</code> مثلًا المنشور ذو المعرّف <code>id: 1</code>. لكن قد يعتمد اختيار المعرّف المطلوب على بيانات خارجية.
تتيح لك Next.js أن تنشئ صفحات تعتمد المسارت الديناميكية dynamic routes إذ تستطيع مثلًا إنشاء ملف يُدعى <code>pages/posts/[id].js</code> لاستعراض منشور مفرد من مدونة وفقًا للمعرِّف الفريد الخاص به <code>id</code>، وسيعرض لك المسار <code>posts/1</code> مثلًا المنشور ذا المعرّف <code>id: 1</code> لكن قد يعتمد اختيار المعرّف المطلوب على بيانات خارجية.


'''مثال''': لنفترض أنك أضفت منشورًا واحدًا (له المعرّف <code>id: 1</code>) إلى قاعدة البيانات، وهكذا سيُصيَّر هذا المسار فقط أثناء بناء التطبيق. لكنك قد تضيف لاحقًا منشورًا ثانيًا له المعرِّف <code>id: 2</code>، وسترغب في تصييره مسبقًا أيضًا، وعندها ستحتاج إلى بيانات خارجية لتعرف أيهما سيُصيّر. لمعالجة هذا الأمر، تتيح لك Next.js تصدير دالة غير متزامنة تُدعى <code>getStaticPaths</code> من الصفحة ذات المسار الديناميكي <code>pages/posts/[id].js</code>، وتُستدعى هذه الدالة أثناء بناء التطبيق لاختيار المسار الذي تريد تصييره مسبقًا:<syntaxhighlight>
'''مثال''': لنفترض أنك أضفت منشورًا واحدًا (له المعرّف <code>id: 1</code>) إلى قاعدة البيانات، وهكذا سيُصيَّر هذا المسار فقط أثناء بناء التطبيق، لكنك قد تضيف لاحقًا منشورًا ثانيًا له المعرِّف <code>id: 2</code>، وسترغب في تصييره مسبقًا أيضًا، وعندها ستحتاج إلى بيانات خارجية لتعرف أيهما سيُصيّر. لمعالجة هذا الأمر، تتيح لك Next.js تصدير دالة غير متزامنة تُدعى <code>getStaticPaths</code> من الصفحة ذات المسار الديناميكي <code>pages/posts/[id].js</code>، وتُستدعى هذه الدالة أثناء بناء التطبيق لاختيار المسار الذي تريد تصييره مسبقًا:<syntaxhighlight lang="javascript">
// تُستدعى هذه الدالة أثناء بناء التطبيق
// تُستدعى هذه الدالة أثناء بناء التطبيق
export async function getStaticPaths() {
export async function getStaticPaths() {
سطر 103: سطر 105:
   return { paths, fallback: false }
   return { paths, fallback: false }
}
}
</syntaxhighlight>لا بد من استخدام الدالة <code>getStaticProps</code> أيضًا في هذا السيناريو للحصول على بيانات المنشور ذو المعرِّف <code>id</code> واستخدام هذه البيانات في التصيير المسبق للصفحة:<syntaxhighlight>
</syntaxhighlight>لا بدّ من استخدام الدالة <code>getStaticProps</code> أيضًا في هذه الحالة للحصول على بيانات المنشور ذو المعرِّف <code>id</code> واستخدام هذه البيانات في التصيير المسبق للصفحة:<syntaxhighlight lang="javascript">
function Post({ post }) {
function Post({ post }) {
   // تصيير المنشور ...
   // تصيير المنشور ...
سطر 114: سطر 116:
// يُستدعى أثناء بناء التطبيق
// يُستدعى أثناء بناء التطبيق
export async function getStaticProps({ params }) {
export async function getStaticProps({ params }) {
   //على معرّف المنشورparams تحوي المعاملات
   //على معرّف المنشور params تحوي المعاملات
   
   
   const res = await fetch(`https://.../posts/${params.id}`)
   const res = await fetch(`https://.../posts/${params.id}`)
سطر 124: سطر 126:


export default Post
export default Post
</syntaxhighlight>راجع [[Next.js/data fetching|توثيق إحضار البيانات]] لتطلع أكثر على عمل الدالة <code>getStaticPaths</code>.
</syntaxhighlight>راجع [[Next.js/data fetching|توثيق إحضار البيانات]] لتطلع أكثر على عمل الدالة <code>[[Next.js/data fetching#.D8.A7.D9.84.D8.AA.D9.88.D9.84.D9.8A.D8.AF .D8.A7.D9.84.D8.B3.D8.A7.D9.83.D9.86 .D9.84.D9.84.D9.85.D8.B3.D8.A7.D8.B1.D8.A7.D8.AA .D8.A8.D8.A7.D8.B3.D8.AA.D8.AE.D8.AF.D8.A7.D9.85 .D8.A7.D9.84.D8.AF.D8.A7.D9.84.D8.A9 getStaticPaths|getStaticPaths]]</code>.


=== متى ينبغي استخدام التوليد الساكن في Next.js ===
=== متى ينبغي استخدام التوليد الساكن في Next.js؟ ===
يُفضّل استخدام التوليد الساكن (بوجود بيانات أو عدم وجودها) دائمًا إن أمكن ذلك، لأن الصفحة ستُبنى دفعة واحدة وتُخدّم من قبل شبكات توصيل المحتوى CDN، مما يزيد في سرعة إيصال المحتوى بدلًا من الإعتماد على الخادم في تصيير الصفحة في كُلِّ مرة تُطلب فيها.
يُفضّل استخدام التوليد الساكن (بوجود بيانات أو عدم وجودها) دائمًا إن أمكن ذلك، لأنّ الصفحة ستُبنى دفعة واحدة وتُخدّم من قبل شبكات توصيل المحتوى CDN، مما يزيد في سرعة إيصال المحتوى بدلًا من الإعتماد على الخادم في تصيير الصفحة في كُلِّ مرة تُطلب فيها.


يمكنك استخدام التصيير الساكن لأنواع متعددة من الصفحات بما فيها:
يمكنك استخدام التصيير الساكن لأنواع متعددة من الصفحات بما فيها:


* صفحات التسويق.
* صفحات التسويق
* المدوّنات.
* المدوّنات
* قوائم المنتجات في المتاجر الإلكترونية.
* قوائم المنتجات في المتاجر الإلكترونية
* صفحات المساعدة والتوثيق.
* صفحات المساعدة والتوثيق


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


ولن يكون التصيير الساكن مناسبًا إن لم يكن بالإمكان تصيير الصفحة مسبقًا قبل أن يطلبها المستخدم. فقد تعرض الصفحة بيانات تُحدَّث باستمرار أو محتوى يتغير مع كل طلب. في حالات كهذه قد تختار إحدى المقارابات التالية:
ولن يكون التصيير الساكن مناسبًا إن لم يكن بالإمكان تصيير الصفحة مسبقًا قبل أن يطلبها المستخدم، فقد تعرض الصفحة بيانات تُحدَث باستمرار أو محتوى يتغير مع كل طلب، وآنذاك قد تختار إحدى المقارابات التالية:


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


== التصيير من جانب الخادم في Next.js ==
== التصيير من جانب الخادم في Next.js ==
<blockquote>يُشار إلى هذه الأسلوب بالاختصار "SSR" أو بعبارة "التصيير الديناميكي"</blockquote>توّلد شيفرة HTML في هذه الحالة عند كل طلب للصفحة. ولاستخدام التصيير من جانب الخادم، لا بد من تصدير دالة غير متزامنة تُدعى <code>getServerSideProps</code> يستدعيها الخادم مع كل طلب.
<blockquote>يُشار إلى هذه الأسلوب بالاختصار "SSR" أو بعبارة "التصيير الديناميكي".</blockquote>تولّد شيفرة HTML في هذه الحالة عند كل طلب للصفحة، ولاستخدام التصيير من جانب الخادم، لا بدّ من تصدير دالة غير متزامنة تُدعى <code>getServerSideProps</code> يستدعيها الخادم مع كل طلب.


لنفرض مثلًا أنك تحتاج إلى تصيير صفحتك باستمرار لتحديث بياناتها (إحضار البيانات من وصلة API خارجية). يمكنك في هذه الحالة استخدام الدالة <code>getServerSideProps</code> في إحضار البيانات المطلوبة وتمريرها إلى الصفحة كالتالي:<syntaxhighlight>
لنفرض مثلًا أنك تحتاج إلى تصيير صفحتك باستمرار لتحديث بياناتها (إحضار البيانات من وصلة API خارجية). يمكنك في هذه الحالة استخدام الدالة <code>getServerSideProps</code> في إحضار البيانات المطلوبة وتمريرها إلى الصفحة كالتالي:<syntaxhighlight lang="javascript">
function Page({ data }) {
function Page({ data }) {
   //تصيير البيانات...
   //تصيير البيانات...
سطر 157: سطر 159:
   const data = await res.json()
   const data = await res.json()


   // تمرير البيانات إلى الصفحة عن طريق الخصائص
   // تمرير البيانات إلى الصفحة عن طريق الخاصيات
   return { props: { data } }
   return { props: { data } }
}
}


export default Page
export default Page
</syntaxhighlight>تشابه الدالة <code>getServerSideProps</code> في عملها الدالة <code>getStaticProps</code> إلا أنها تُستدعى عند كل طلب بدلًا من استدعائها أثناء بناء التطبيق. راجع [[Next.js/data fetching|توثيق إحضار البيانات]] لتطلع أكثر على عمل الدالة <code>getServerSideProps</code>.
</syntaxhighlight>تشابه الدالة <code>getServerSideProps</code> في عملها الدالة <code>getStaticProps</code> إلّا أنها تُستدعى عند كل طلب بدلًا من استدعائها أثناء بناء التطبيق. راجع [[Next.js/data fetching|توثيق إحضار البيانات]] لتطلع أكثر على عمل الدالة <code>[[Next.js/data fetching#.D8.A7.D9.84.D8.AA.D8.B5.D9.8A.D9.8A.D8.B1 .D9.85.D9.86 .D8.AC.D8.A7.D9.86.D8.A8 .D8.A7.D9.84.D8.AE.D8.A7.D8.AF.D9.85 .D9.81.D9.8A Next.js .D8.A8.D8.A7.D8.B3.D8.AA.D8.AE.D8.AF.D8.A7.D9.85 .D8.A7.D9.84.D8.AF.D8.A7.D9.84.D8.A9 getServerSideProps|getServerSideProps]]</code>.


== خلاصة ==
== خلاصة ==
ناقشنا في الفقرات السابقة نمطي التصيير المسبق للصفحات في Next.js:
ناقشنا في الفقرات السابقة نمطي التصيير المسبق للصفحات في Next.js:


* '''التوليد الساكن (مستحسن)''': توّلد شيفرة HTML وفق هذا النمط أثناء بناء الصفحة ويُعاد استخدامها عند كل طلب. ولاستخدام هذا النمط لا بد من تصدير مكوّن الصفحة أو تصدير الدالة <code>getStaticProps</code> (والدالة <code>getStaticPaths</code> إن اقتضى الأمر). وهذا النمط مناسب جدًا للصفحات التي يمكن تصييرها مسبقًا قبل أن يطلبها المستخدم، كما يمكنك استخدامها مع أسلوب التصيير من جانب العميل لإحضار بيانات إضافية.
* '''التوليد الساكن (مستحسن)''': تولّد شيفرة HTML وفق هذا النمط أثناء بناء الصفحة ويُعاد استخدامها عند كل طلب. ولاستخدام هذا النمط لا بدّ من تصدير مكوّن الصفحة أو تصدير الدالة <code>getStaticProps</code> (والدالة <code>getStaticPaths</code> إن اقتضى الأمر). وهذا النمط مناسب جدًا للصفحات التي يمكن تصييرها مسبقًا قبل أن يطلبها المستخدم، كما يمكنك استخدامها مع أسلوب التصيير من جانب العميل لإحضار بيانات إضافية.


* '''التصيير من جانب الخادم''':  
* '''التصيير من جانب الخادم''': تولّد شيفرة HTML عند كل طلب. ولاستخدام هذا النمط، لا بدّ من تصدير الدالة <code>getServerSideProps</code> ولا تستخدم هذا النمط إلا للضرورة القصوى لأن له  أداءً أبطأ من التوليد الساكن.
* توّلد شيفرة HTML عند كل طلب. ولاستخدام هذا النمط، لا بد من تصدير الدالة <code>getServerSideProps</code>. لا تستخدم هذا النمط إلا للضرورة القصوى لأنه يعطي أداءً أبطأ من التوليد الساكن.
 
== انظر أيضًا ==
 
* [[Next.js/data fetching|إحضار البيانات في Next.js]]
* [[Next.js/preview mode|نمط استعراض الصفحات في Next.js]]
* [[Next.js/Routing|توجيه المسارات في Next.js]]
* [[Next.js/typescript|استخدام TypeScript في Next.js]]


== المصادر ==
== المصادر ==
[https://nextjs.org/docs/basic-features/pages توثيق Next.JS: الصفحة Pages]
 
[[تصنيف:Next.js]]
* الصفحة [https://nextjs.org/docs/basic-features/pages Pages] من توثيق Next.js الرسمي.
[[تصنيف:Next.js|{{SUBPAGENAME}}]]
[[تصنيف:Next.js Basic Features|{{SUBPAGENAME}}]]

المراجعة الحالية بتاريخ 17:15، 3 يناير 2023

ملاحظة: نوفر دعمًا لعملية توجيه مُحسَّنة للمسارات في Next.js، واقرأ تدوينة Layouts RFC لمزيد من التفاصيل.

الصفحة page هي مكوّن React مصدر عن ملفات موجودة في المجلد pages وتمتلك إحدى الامتدادات التالية: js. أو jsx. أو ts. أو tsx.. تقترن كل صفحة بمسار يتعلق باسم الملف، فلو أنشأت على سبيل المثال الملف pages/about.js الذي يصدّر مكوّن React التالي، ستتمكن من الوصول إليه من خلال المسار ‎/about.

function About() {
  return <div>About</div>
}

export default About

صفحات بمسارات ديناميكية في Next.js

تدعم المسارات الديناميكية للصفحات. فإن انشأت الملف pages/posts/[id].js مثلًا، أمكنك الوصول إليه بكتابة المسار posts/1 أو posts/2 وهكذا.

التصيير المسبق للصفحات في Next.js

تصيّر Next.js الصفحات مسبقًا pre-render، ويعني ذلك توليد شيفرة HTML لكل صفحة مسبقًا بدلًا من إلقاء الحمل كاملًا على محرّك JavaScript الذي يعمل من طرف العميل. وقد يُحسّن هذا الأمر الأداء، كما يُحسن ترتيب ظهور الصفحة في محرّكات البحث SEO (سيو أفضل).

تُزوَد شيفرة HTML المولَّدة لكل صفحة بحد أدنى من شيفرة JavaScript الضرورية لعملها. وعندما يُحمّل المتصفح الصفحة، ستُنفَّذ شيفرة JavaScript لتمنح الصفحة تفاعلية أكبر (تُدعى هذه العملية بالترطيب hydration).

نمطي التصيير المسبق

للتصيير المسبق في Next.js نمطين هما: التوليد الساكن Static Generation والتصيير من جانب الخادم Server-side Rendering ويقتصر الفارق بينهما على اللحظة التي تولّد فيها شيفرة HTML.

  • التوليد الساكن (مُستحسن): تولّد شيفرة HTML وفق هذا النمط أثناء بناء الصفحة ويُعاد استخدامها عند كل طلب.
  • التصيير من جانب الخادم: تولّد شيفرة HTML عند كل طلب.

تمنحك Next.js القدرة على اختيار نمط التصيير المسبق لكل صفحة، وبالتالي ستتمكن من بناء تطبيقات هجينة عندما تستخدم التوليد الساكن لمعظم صفحاته وتجعل تصيير بعضها الآخر من جانب الخادم.

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

بالإمكان أيضًا استخدام التصيير من جانب العميل Client-side Rendering جنبًا إلى جنب مع التوليد الساكن أو التصيير من جانب الخادم، أي أنه بالإمكان تصيير جزء من الصفحة كليًا بواسطة JavaScript منفَّذة من طرف العميل، ولمزيد من المعلومات راجع توثيق إحضار البيانات.

التوليد الساكن للشيفرة في Next.js

تولّد شيفرة HTML عند استخدام نمط التوليد الساكن أثناء بناء التطبيق. ويعني ذلك من منظور مرحلة الإنتاج أنّ توليد HTML يجري عند تنفيذ الأمر next build. تُستخدم بعد ذلك هذه الشيفرة مع كل طلب، ويمكن تخزينها مؤقتًا ضمن شبكة توصيل المحتوى CDN، وبالإمكان توليد صفحات تحوي بيانات في Next.js أو لا، لنلق نظرة على ذلك.

التوليد الساكن لصفحات بلا بيانات

تصيّر Next.js الصفحات مسبقًا وفق نمط التوليد الساكن افتراضيًا، وإليك مثالًا:

function About() {
  return <div>About</div>
}

export default About

لاحظ أن هذه الصفحة ليست بحاجة إلى جلب أي بيانات من أي مصدر خارجي لعرضها، وبذلك تولد Next.js صفحة HTML ساكنة ثابتة لا تتغير أثناء عملية البناء.

التوليد الساكن لصفحات تحتوي بيانات

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

  1. getStaticProps: وتُسخدم عندما يعتمد محتوى صفحتك على بيانات خارجية.
  2. getStaticPaths: وتُستخدم عندما تعتمد المسارات paths في الصفحة على بيانات خارجية، وعادة ما تُستخدم إلى جانب الدالة getStaticProps.

الحالة الأولى: اعتماد الصفحة على بيانات خارجية

وكمثال على ذلك مدوّنة قد تحتاج إلى إحضار قائمة بالمنشورات من نظام إدارة المحتوى content management system:

// (عليك إحضار المنشورات (باستدعاء وصلة برمجية خارجية
// قبل أن تُصيَّر هذه الصفحة مسبقًا
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

export default Blog

تسمح لك Next.js أن تصدّر دالة غير متزامنة تُدعى getStaticProps من الملف ذاته إن أردت إحضار تلك البيانات في مرحلة التصيير المسبق، وتُستدعى هذ الدالة أثناء بناء التطبيق وتسمح لك بتمرير البيانات المُحضرة إلى خاصيات الصفحة props في مرحلة التصيير المسبق.

function Blog({ posts }) {
  // عرض المنشورات ...
}

// تُستدعى هذه الدالة أثناء بناء التطبيق
export async function getStaticProps() {
  //خارجية API تستدعى وصلة 
  const res = await fetch('https://.../posts')
  const posts = await res.json()
  // المنشورات كخاصيات أثناء بناء التطبيق Blog يتلقى المكوّن 
  //{ props: { posts } }بإعادة
  return {
    props: {
      posts,
    },
  }
}

export default Blog

راجع توثيق إحضار البيانات لتطلع أكثر على عمل الدالة getStaticProps.

الحالة الثانية: اعتماد مسارات الصفحة على بيانات خارجية

تتيح لك Next.js أن تنشئ صفحات تعتمد المسارت الديناميكية dynamic routes إذ تستطيع مثلًا إنشاء ملف يُدعى pages/posts/[id].js لاستعراض منشور مفرد من مدونة وفقًا للمعرِّف الفريد الخاص به id، وسيعرض لك المسار posts/1 مثلًا المنشور ذا المعرّف id: 1 لكن قد يعتمد اختيار المعرّف المطلوب على بيانات خارجية.

مثال: لنفترض أنك أضفت منشورًا واحدًا (له المعرّف id: 1) إلى قاعدة البيانات، وهكذا سيُصيَّر هذا المسار فقط أثناء بناء التطبيق، لكنك قد تضيف لاحقًا منشورًا ثانيًا له المعرِّف id: 2، وسترغب في تصييره مسبقًا أيضًا، وعندها ستحتاج إلى بيانات خارجية لتعرف أيهما سيُصيّر. لمعالجة هذا الأمر، تتيح لك Next.js تصدير دالة غير متزامنة تُدعى getStaticPaths من الصفحة ذات المسار الديناميكي pages/posts/[id].js، وتُستدعى هذه الدالة أثناء بناء التطبيق لاختيار المسار الذي تريد تصييره مسبقًا:

// تُستدعى هذه الدالة أثناء بناء التطبيق
export async function getStaticPaths() {
  //خارجية لإحضار منشورات المدونة API استدع وصلة 
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // الحصول على المسارات التي نريد تصييرها بشكل أولي وفقًا لمعرّف المنشور
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // سنصيّر فقط هذه المسارات أثناء بناء التطبيق
  // { fallback: false } 
  // بينما سيعطي الخادم الرسالة 404 لبقية المسارات
  return { paths, fallback: false }
}

لا بدّ من استخدام الدالة getStaticProps أيضًا في هذه الحالة للحصول على بيانات المنشور ذو المعرِّف id واستخدام هذه البيانات في التصيير المسبق للصفحة:

function Post({ post }) {
  // تصيير المنشور ...
}

export async function getStaticPaths() {
  // ...
}

// يُستدعى أثناء بناء التطبيق
export async function getStaticProps({ params }) {
  //على معرّف المنشور params تحوي المعاملات
 
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  //props تمرير بيانات المنشور إلى الصفحة من خلال الخصائص 
  return { props: { post } }
}

export default Post

راجع توثيق إحضار البيانات لتطلع أكثر على عمل الدالة getStaticPaths.

متى ينبغي استخدام التوليد الساكن في Next.js؟

يُفضّل استخدام التوليد الساكن (بوجود بيانات أو عدم وجودها) دائمًا إن أمكن ذلك، لأنّ الصفحة ستُبنى دفعة واحدة وتُخدّم من قبل شبكات توصيل المحتوى CDN، مما يزيد في سرعة إيصال المحتوى بدلًا من الإعتماد على الخادم في تصيير الصفحة في كُلِّ مرة تُطلب فيها.

يمكنك استخدام التصيير الساكن لأنواع متعددة من الصفحات بما فيها:

  • صفحات التسويق
  • المدوّنات
  • قوائم المنتجات في المتاجر الإلكترونية
  • صفحات المساعدة والتوثيق

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

ولن يكون التصيير الساكن مناسبًا إن لم يكن بالإمكان تصيير الصفحة مسبقًا قبل أن يطلبها المستخدم، فقد تعرض الصفحة بيانات تُحدَث باستمرار أو محتوى يتغير مع كل طلب، وآنذاك قد تختار إحدى المقارابات التالية:

  • استخدام التصيير الساكن مع التصيير من جانب العميل: إذ يمكن تجاوز التصيير المسبق لبعض أجزاء الصفحة ومن ثم تستخدم شيفرة JavaScript من جانب العميل (أي يُنفِّذ المتصفح شيفرة JavaScript) لتصييرها عندما تصل إلى المستخدم، وسنرى ذلك لاحقًا عند الحديث عن إحضار البيانات.
  • استخدام التصيير من جانب الخادم: تُصيّر Next.js الصفحة في هذه الحالة عند كل طلب وستكون الصفحة أبطأ لأنها لن تُخزّن مؤقتًا ضمن شبكة توزيع المحتوى، لكنها ستكون محدّثة دائمًا، وهذا ما سنتحدث عنه تاليًا.

التصيير من جانب الخادم في Next.js

يُشار إلى هذه الأسلوب بالاختصار "SSR" أو بعبارة "التصيير الديناميكي".

تولّد شيفرة HTML في هذه الحالة عند كل طلب للصفحة، ولاستخدام التصيير من جانب الخادم، لا بدّ من تصدير دالة غير متزامنة تُدعى getServerSideProps يستدعيها الخادم مع كل طلب. لنفرض مثلًا أنك تحتاج إلى تصيير صفحتك باستمرار لتحديث بياناتها (إحضار البيانات من وصلة API خارجية). يمكنك في هذه الحالة استخدام الدالة getServerSideProps في إحضار البيانات المطلوبة وتمريرها إلى الصفحة كالتالي:

function Page({ data }) {
  //تصيير البيانات...
}

// تُستدعى هذه الدالة عند كل طلب
export async function getServerSideProps() {
  // Fetch data from external API
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // تمرير البيانات إلى الصفحة عن طريق الخاصيات
  return { props: { data } }
}

export default Page

تشابه الدالة getServerSideProps في عملها الدالة getStaticProps إلّا أنها تُستدعى عند كل طلب بدلًا من استدعائها أثناء بناء التطبيق. راجع توثيق إحضار البيانات لتطلع أكثر على عمل الدالة getServerSideProps.

خلاصة

ناقشنا في الفقرات السابقة نمطي التصيير المسبق للصفحات في Next.js:

  • التوليد الساكن (مستحسن): تولّد شيفرة HTML وفق هذا النمط أثناء بناء الصفحة ويُعاد استخدامها عند كل طلب. ولاستخدام هذا النمط لا بدّ من تصدير مكوّن الصفحة أو تصدير الدالة getStaticProps (والدالة getStaticPaths إن اقتضى الأمر). وهذا النمط مناسب جدًا للصفحات التي يمكن تصييرها مسبقًا قبل أن يطلبها المستخدم، كما يمكنك استخدامها مع أسلوب التصيير من جانب العميل لإحضار بيانات إضافية.
  • التصيير من جانب الخادم: تولّد شيفرة HTML عند كل طلب. ولاستخدام هذا النمط، لا بدّ من تصدير الدالة getServerSideProps ولا تستخدم هذا النمط إلا للضرورة القصوى لأن له أداءً أبطأ من التوليد الساكن.

انظر أيضًا

المصادر

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