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

من موسوعة حسوب
لا ملخص تعديل
طلا ملخص تعديل
 
(1 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:الانتقال إلى Next.js}}</noinclude>
<noinclude>{{DISPLAYTITLE:الانتقال إلى Next.js}}</noinclude>
صُمِّمت Next.js لكي يجري تبنيها تدريجيًا، إذ ستكون قادرًا على متابعة العمل على شيفرة جاهزة وإضافة المقدار الذي تريده من شيفرة React. فإن بدأت بكمية صغيرة من الشيفرة ووسعتها تدريجيًا بإضافة صفحات جديدة، سيمنع ذلك خروج الميزات عن الطريق الذي رسم لها فيما لو أعدت كتابة كل شيء بالكامل.
صُمِّمت Next.js لكي يجري تبنيها تدريجيًا، إذ ستكون قادرًا على متابعة العمل على شيفرة جاهزة حالية وإضافة المقدار الذي تريده من شيفرة React. فإن بدأت بكمية صغيرة من الشيفرة ووسعتها تدريجيًا بإضافة صفحات جديدة، سيسهل ذلك عليك تبني Next.js في مشاريعك وتجنب إعادة كتابة كل شيء بالكامل.


== استراتيجيات العمل ==
== استراتيجيات العمل ==


=== المسارات الفرعية ===
=== المسارات الفرعية Subpath ===
تقتضي الاستراتيجية الأولى بتهيئة الخادم أو الخادم الوكيل لوضع كل ما يتعلق بتطبيق Next.js في نفس المسار الفرعي (ضمن مجلد فرعي). فقد يكون موقعك الإلكتروني مثلًا <code>example.com</code> ومن ثم تهيئ المسار الفرعي <code>example.com/store</code> على الخادم ليضم تطبيق لمتجر إلكتروني.
تقتضي الاستراتيجية الأولى بتهيئة الخادم أو الخادم الوكيل لوضع كل ما يتعلق بتطبيق Next.js في نفس المسار الفرعي (ضمن مجلد فرعي). فقد يكون موقعك الإلكتروني مثلًا <code>example.com</code> ومن ثم تهيئ المسار الفرعي <code>example.com/store</code> على الخادم ليضم تطبيق لمتجر إلكتروني.


بإمكانك تهيئة موجودات وروابط تطبيق Next.js لتعمل تلقائيًا عند طلب الوجهة <code>store/</code>، وذلك باستخدام [[Next.js/next.config.js|<code>basePath</code>]]. وبما أن كل صفحة من صفحات Next.js هي وجهة قائمة بنفسها، يمكنك الوصول إلى الصفحة <code>pages/products.js</code> مثلًا عبر المسار <code>example.com/store/products</code>. <syntaxhighlight lang="javascript">
بإمكانك تهيئة أصول assets وروابط تطبيق Next.js لتعمل تلقائيًا عند طلب الوجهة <code>store/</code>، وذلك باستخدام [[Next.js/next.config.js|<code>basePath</code>]]. وبما أن كل صفحة من صفحات Next.js هي وجهة قائمة بنفسها، يمكنك الوصول إلى الصفحة <code>pages/products.js</code> مثلًا عبر المسار <code>example.com/store/products</code>. <syntaxhighlight lang="javascript">
// next.config.js
// next.config.js


سطر 13: سطر 13:
   basePath: '/store',
   basePath: '/store',
}
}
</syntaxhighlight><blockquote>تتوفر هذه الميزة ابتداءً من الإصدار 9.5. فإن كنت تستخدم إصدارًا أقدم، يستحسن ترقية إصدارك ثم التجريب.</blockquote>
</syntaxhighlight>
 
== الدالة rewrites ==
== الدالة rewrites ==
تقتضي الاستراتيجية الثانية إنشاء تطبيق Next.js جديد يشير إلى عنوان URL الجذري للنطاق domain الذي تستخدمه. استخدم بعد ذلك الدالة [[Next.js/next.config.js|<code>rewrites</code>]] ضمن ملف التهيئة لكي تُحوَّل بعض المسارات إلى التطبيق الموجود.  
تقتضي الاستراتيجية الثانية إنشاء تطبيق Next.js جديد يشير إلى عنوان URL الجذري للنطاق domain الذي تستخدمه. استخدم بعد ذلك الدالة [[Next.js/next.config.js|<code>rewrites</code>]] ضمن ملف التهيئة لكي تُحوَّل بعض المسارات إلى التطبيق الموجود.  


لنفرض مثلًا أنك أنشأت تطبيق Next.js كي يُخدّم عبر النطاق <code>example.com</code> وله ملف التهيئة <code>next.config.js</code>. عندها ستتعامل Next.js مع الصفحات التي أضفتها إلى تطبيقك (مثل <code>about/</code> إن أضفت <code>pages/about.js</code>)، بينما ستحوّل أية طلبات أخرى (مثل <code>dashboard/</code>) إلى <code>proxy.example.com</code>.<syntaxhighlight lang="javascript">
 
 
لنفرض مثلًا أنك أنشأت تطبيق Next.js كي يُخدّم عبر النطاق <code>example.com</code> وله ملف التهيئة <code>next.config.js</code>. عندها ستتعامل Next.js مع الصفحات التي أضفتها إلى تطبيقك (مثل <code>about/</code> إن أضفت <code>pages/about.js</code>)، بينما ستحوّل أية طلبات أخرى (مثل <code>dashboard/</code>) إلى <code>proxy.example.com</code>.
 
'''ملاحظة''': إن كنت تستعمل <code>fallback: true/'blocking'‎</code> في <code>getStaticPaths</code>، فلن يعمل الالتقاط الكامل catch-all ضمن <code>rewrites</code> المُعرف في الملف <code>next.config.js</code> إذ ستلتقطها <code>getStaticPaths</code>.<syntaxhighlight lang="javascript">
// next.config.js
// next.config.js


سطر 36: سطر 39:
     //في الإصدارات مادون 10.1 rewrite يمكنك استخدام الدالة غير الفعالة  
     //في الإصدارات مادون 10.1 rewrite يمكنك استخدام الدالة غير الفعالة  
     return [
     return [
       // لا يد من اعريف دالة غير فعالة لتحرض عملية التحقق
       // لابد من تعريف دالة غير فعالة لتحرض عملية التحقق
       // من كل الصفحات الساكنة قبل أن نحاول تحويل المسار
       // من كل الصفحات الساكنة قبل أن نحاول تحويل المسار
       {
       {
سطر 49: سطر 52:
   },
   },
}
}
</syntaxhighlight><blockquote>تتوفر هذه الميزة ابتداءً من الإصدار 9.5. فإن كنت تستخدم إصدارًا أقدم، يستحسن ترقية إصدارك ثم التجريب.</blockquote>
</syntaxhighlight>'''ملاحظة''': إن كنت تنتقل تدريجيا إلى الوجهات الديناميكية مثل <code>‎[slug]</code> وكنت تستعمل <code>fallback: true</code> أو <code>fallback: 'blocking'‎</code> مع <code>rewrite</code>، فتأكد من أن تشمل حالة عدم العثور على صفحة page not found، إذ عندما تلتقط Next.js الوجهات الديناميكية فإنها تتوقف عن التحقق من أي وجهات أخرى. استعمال <code>notFound: true</code> في <code>getStaticProps</code> سيعيد صفحة 404 دون تطبيق <code>rewrite</code>، فإن لم تكن ترغب بذلك، يمكنك استعمال <code>getServerSideProps</code> مع ترويسة التحكم بالتخزين المؤقت <code>stale-while-revalidate</code> عند إعادة الخاصيات props وبعدها يمكنك إعادة التوجيه proxy يدويًا إلى الواجهة الخلفية الحالية باستعمال أدوات مثل [https://github.com/vercel/next.js/discussions/38839#discussioncomment-3744442 http-proxy] بدلًا من إعادة <code>notFound: true</code>.
 
=== واجهات أمامية مُصغرة مع مستودعات مفردة ونطاقات فرعية ===
=== واجهات أمامية مُصغّرة مع مستودعات مفردة ونطاقات فرعية ===
تجعل Next.js و Vercel عملية بناء الواجهات الأمامية المصغّرة أو المجزّأة [https://martinfowler.com/articles/micro-frontends.html micro-frontends] ونشرها إلى مستودع مفرد [https://vercel.com/blog/monorepos Monorepo] أمرًا مباشرًا وبسيطًا. يسمح لك ذلك باستخدام النطاقات الفرعية لتبنّي تطبيقات جديدة تدريجيًا. ومن مزايا استخدام الواجهة الأمامية المصغّرة:
<u>تجعل و</u>بناء الواجهات الأمامية المصغّرة أو المجزّأة [https://martinfowler.com/articles/micro-frontends.html micro-frontends] ونشرها إلى مستودع مفرد [https://vercel.com/blog/monorepos Monorepo] أمرًا مباشرًا وبسيطًا. يسمح لك ذلك باستخدام النطاقات الفرعية لتبنّي تطبيقات جديدة تدريجيًا. ومن مزايا استخدام الواجهة الأمامية المصغّرة:


* صغر حجمها وتماسكها وسهولة إدارة شيفرتها.
* صغر حجمها وتماسكها وسهولة إدارة شيفرتها.
سطر 61: سطر 63:


== الانتقال من Gatesby ==
== الانتقال من Gatesby ==
يساعدك هذا الدليل في نقل تطبيقك Gatsby إلى تطبيق <u>Next.js؛ إذ يسمح لك الانتقال إلى</u> أن:
يساعدك هذا الدليل في نقل تطبيقك Gatsby إلى تطبيق Next.js؛ إذ يسمح لك الانتقال إلى Next.js أن:


* تختار استراتيجية [[Next.js/data fetching|إحضار البيانات]] التي تريد لكل صفحة بشكل مستقل.
* تختار استراتيجية [[Next.js/data fetching|إحضار البيانات]] التي تريد لكل صفحة بشكل مستقل.
سطر 72: سطر 74:
وهي الخطوة الأولى في عملية الانتقال وعليك تنفيذ ما يلي:
وهي الخطوة الأولى في عملية الانتقال وعليك تنفيذ ما يلي:


* إزالة كل الحزم <u>المتعلقة بلغة</u> (ابق فقط <code>react</code> و <code>react-dom</code>)
* إزالة كل الحزم المتعلقة ب Gatsby (ابق فقط <code>react</code> و <code>react-dom</code>)
* ثبِّت <code>next</code>.
* ثبِّت <code>next</code>.
* أضف الأوامر المتعلقة بلغة Next.js إلى <code>scripts</code> وأولها <code>next dev</code> الذي يشغّل خادم التطوير على العنوان <code>localhost:3000</code>. أما ثانيها فهو <code>next build</code> و <code>next start</code> لإنشاء وتشغيل نسخة الإنتاج.
* أضف الأوامر Next.js إلى <code>scripts</code> وأولها <code>next dev</code> الذي يشغّل خادم التطوير على العنوان <code>localhost:3000</code>. أما ثانيها فهو <code>next build</code> و <code>next start</code> لإنشاء وتشغيل نسخة الإنتاج.


إليك مثالًا عن <code>package.json</code>:<syntaxhighlight lang="json">
إليك مثالًا عن <code>package.json</code>:<syntaxhighlight lang="json">
سطر 91: سطر 93:
</syntaxhighlight>
</syntaxhighlight>


=== الموجودات الساكنة والخرج المُصرَّف ===
=== الأصولو الساكنة والخرج المُصرَّف ===
تستخدم Gatsby المجلد <code>public</code> لوضع ملفات الخرج المصرَّفة بينما تستخدم Next.js هذا المجلد لوضع الموجودات الساكنة. إليك خطوات الانتقال في هذه المرحلة:
تستخدم Gatsby المجلد <code>public</code> لوضع ملفات الخرج المصرَّفة بينما تستخدم Next.js هذا المجلد لوضع الأصول الساكنة static assets. إليك خطوات الانتقال في هذه المرحلة:


* أزل الإشارة إلى المجلدين <code>/cache.</code> و <code>public</code> من الملف <code>gitignore.</code> واحذف المجلدين.
* أزل الإشارة إلى المجلدين <code>/cache.</code> و <code>public</code> من الملف <code>gitignore.</code> واحذف المجلدين.
سطر 98: سطر 100:
* أضف <code>next.</code> إلى <code>gitignore.</code>.
* أضف <code>next.</code> إلى <code>gitignore.</code>.


=== إنشاء الوجهات ===
=== إنشاء الوجهات Routes ===
تدعم كلا اللغتين Gatsby و Next المجلد <code>pages</code> الذي يستخدم [[Next.js/Routing|أسلوب توجيه يعتمد على نظام الملفات]]. تستخدم المجلد <code>src/pages</code> الذي [[Next.js/src directory|تدعمه أيضًا Next.js]]. تُنشئ Gatsby الوجهات الديناميكية باستخدام الواجهة البرمجية <code>createPages</code> ضمن الملف <code>gatsby-node.js</code>. ويمكنك في Next استخدام [[Next.js/Routing#.D8.A7.D9.84.D9.88.D8.AC.D9.87.D8.A7.D8.AA%20.D8.A7.D9.84.D8.AF.D9.8A.D9.86.D8.A7.D9.85.D9.8A.D9.83.D9.8A.D8.A9%20.D9.81.D9.8A%20Next.js|الوجهات الديناميكية]] ضمن المجلد <code>pages</code> للحصول على نفس التأثير. وبدلًا من وجود مجلد بالاسم <code>template</code>، يمكنك استخدام مكوّنات React ضمن ملف الوجهة الديناميكية:
تدعم كلا Gatsby و Next المجلد <code>pages</code> الذي يستخدم [[Next.js/Routing|أسلوب توجيه يعتمد على نظام الملفات]]. تستخدم المجلد <code>src/pages</code> الذي [[Next.js/src directory|تدعمه أيضًا Next.js]]. تُنشئ Gatsby الوجهات الديناميكية باستخدام الواجهة البرمجية <code>createPages</code> ضمن الملف <code>gatsby-node.js</code>. ويمكنك في Next استخدام [[Next.js/Routing#.D8.A7.D9.84.D9.88.D8.AC.D9.87.D8.A7.D8.AA%20.D8.A7.D9.84.D8.AF.D9.8A.D9.86.D8.A7.D9.85.D9.8A.D9.83.D9.8A.D8.A9%20.D9.81.D9.8A%20Next.js|الوجهات الديناميكية]] ضمن المجلد <code>pages</code> للحصول على نفس التأثير. وبدلًا من وجود مجلد بالاسم <code>template</code>، يمكنك استخدام مكوّنات React ضمن ملف الوجهة الديناميكية:


* '''في Gatsby''': أنشئ مسارات ديناميكية لكل منشور مثلًا باستخدام الواجهة <code>createPages</code> ومن ثم أنشئ ملفًا يمثل قالبًا لهذه المنشورات ضمن <code>src/templates/blog-post.js</code>.
* '''في Gatsby''': أنشئ مسارات ديناميكية لكل منشور مثلًا باستخدام الواجهة <code>createPages</code> ومن ثم أنشئ ملفًا يمثل قالبًا لهذه المنشورات ضمن <code>src/templates/blog-post.js</code>.
سطر 131: سطر 133:
=== إحضار البيانات ===
=== إحضار البيانات ===
يظهر الاختلاف الجذري بين Gatsby و Next.js في طريقة إحضار البيانات. إذ يرتكز خيار Gatsby على "GraphQL" في إحضار البيانات إلى التطبيق، بينما عليك أن تختار في Next.js الاستراتيجية التي تريد ومن ضمنها "GraphQL".  
يظهر الاختلاف الجذري بين Gatsby و Next.js في طريقة إحضار البيانات. إذ يرتكز خيار Gatsby على "GraphQL" في إحضار البيانات إلى التطبيق، بينما عليك أن تختار في Next.js الاستراتيجية التي تريد ومن ضمنها "GraphQL".  


تستخدم Gatsby الدالة <code>graphql</code> لاستعلام البيانات في صفحات الموقع بما فيها البيانات المحلية والبعيدة ومعلومات التهيئة الخاصة بالموقع، كما تسمح بإنشاء صفحات ساكنة فقط. أما في Next.js، بإمكانك اختيار استراتيجية [[Next.js/data fetching|إحضار البيانات]] الخاصة بكل [[Next.js/pages|صفحة]]. إذ تسمح لك الدالة <code>getServerSideProps</code> مثلًا بتنفيذ التصيير من جانب الخادم، بينما بإمكانك تصدير الدالتين <code>getStaticProps</code> / <code>getStaticPaths</code> ضمن الصفحة لتوليد صفحات ساكنة بدلًا من تنفيذ <code>pageQuery</code>. إليك مثالًا:<syntaxhighlight lang="javascript">
تستخدم Gatsby الدالة <code>graphql</code> لاستعلام البيانات في صفحات الموقع بما فيها البيانات المحلية والبعيدة ومعلومات التهيئة الخاصة بالموقع، كما تسمح بإنشاء صفحات ساكنة فقط. أما في Next.js، بإمكانك اختيار استراتيجية [[Next.js/data fetching|إحضار البيانات]] الخاصة بكل [[Next.js/pages|صفحة]]. إذ تسمح لك الدالة <code>getServerSideProps</code> مثلًا بتنفيذ التصيير من جانب الخادم، بينما بإمكانك تصدير الدالتين <code>getStaticProps</code> / <code>getStaticPaths</code> ضمن الصفحة لتوليد صفحات ساكنة بدلًا من تنفيذ <code>pageQuery</code>. إليك مثالًا:<syntaxhighlight lang="javascript">
سطر 170: سطر 170:
   }
   }
}
}
</syntaxhighlight>سترى عادة ملحقات plugins في Gatsby لقراءة منظومة الملفات (<code>gatsby-source-filesystem</code>) أو التعامل مع تنسيق Markdown من خلال (<code>gatsby-transformer-remark</code>) وغيرها. فالمثال النموذجي الأكثر شعبية لمبتدئي تطبيقات المنشورات، قد استخدم [https://github.com/gatsbyjs/gatsby-starter-blog/blob/master/package.json 15 حزمة Gatsby] خاصة. تأخذ Next في المقابل نهجًا آخر، إذ تُضمِّن الميزات كثيرة الاستعمال مباشرة ضمن إطار العمل، وتمنح المستخدم تحكمًا كاملًا في دعم التطبيق بحزم خارجية. فبدلًا من فصل شيفرة القراءة من منظومة الملفات ضمن ملحق، بإمكانك استخدام حزمة Node.js الأصلية <code>fs</code> ضمن الدالتين <code>getStaticProps</code> / <code>getStaticPaths</code> لقراءة منظومة الملفات:<syntaxhighlight lang="javascript">
</syntaxhighlight>سترى عادة ملحقات plugins في Gatsby لقراءة منظومة الملفات <code>gatsby-source-filesystem</code> أو التعامل مع تنسيق Markdown من خلال <code>gatsby-transformer-remark</code> وغيرها. فالمثال النموذجي الأكثر شعبية لمبتدئي تطبيقات المنشورات، قد استخدم [https://github.com/gatsbyjs/gatsby-starter-blog/blob/master/package.json 15 حزمة Gatsby] خاصة. تأخذ Next في المقابل نهجًا آخر، إذ تُضمِّن الميزات كثيرة الاستعمال مباشرة ضمن إطار العمل، وتمنح المستخدم تحكمًا كاملًا في دعم التطبيق بحزم خارجية. فبدلًا من فصل شيفرة القراءة من منظومة الملفات ضمن ملحق، بإمكانك استخدام حزمة Node.js الأصلية <code>fs</code> ضمن الدالتين <code>getStaticProps</code> / <code>getStaticPaths</code> لقراءة منظومة الملفات:<syntaxhighlight lang="javascript">
// src/lib/blog.js
// src/lib/blog.js
//date-fns و gray-matter ثبِّت  
//date-fns و gray-matter ثبِّت  
سطر 198: سطر 198:
</syntaxhighlight>
</syntaxhighlight>


=== مكوّن الصوّر وتحسين الصور ===
=== مكون الصور وتحسين الصور ===
تمتلك Next.js [[Next.js/image optimization|مكوِّن صور مدمج وطريقة تحسين مدمجة للصور]]. إذ يُعد المكوِّن [[Next.js/next image|<code>next/image</code>]] امتدادًا لعنصر الصورة <code><img></code> في HTML، وقد طوّر ليلائم مواقع الويب الحديثة.
تمتلك Next.js [[Next.js/image optimization|مكوِّن صور مدمج وطريقة تحسين مدمجة للصور]]. إذ يُعد المكوِّن [[Next.js/next image|<code>next/image</code>]] امتدادًا لعنصر الصورة <code><img></code> في HTML، وقد طوّر ليلائم مواقع الويب الحديثة.


يتيح لك التحسين التقائي للصور إعادة تحجيم الصورة وتحسينها وتقديمها بامتدادات حديثة مثل [https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types WebP] عندما يدعمها المتصفح. يقلل ذلك من الدفع بصورة كبيرة إلى أجهزة لها نافذة عرض صغيرة، كما يسمح للغة Next.js بالتبني التلقائي لتنسيقات الصور المستقبلية، وتقديمها للمتصفح الذي يدعمها.
يتيح لك التحسين التقائي للصور إعادة تحجيم الصورة وتحسينها وتقديمها بامتدادات حديثة مثل [https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types WebP] عندما يدعمها المتصفح. يقلل ذلك من الدفع بصورة كبيرة إلى أجهزة لها نافذة عرض صغيرة، كما يسمح لـ Next.js بالتبني التلقائي لتنسيقات الصور المستقبلية، وتقديمها للمتصفح الذي يدعمها.


==== الإنتقال بالصور من Gatsby ====
==== الإنتقال بالصور من Gatsby ====
سطر 241: سطر 241:
ستجد البيانات الوصفية (الاسم والوصف وغيرها) للموقع المبني باستخدام Gatsby ضمن الملف <code>gatsby-config.js</code> وتُستعرض بعد ذلك من قبل واجهة GraphQL البرمجية التي تتعامل معها من خلال <code>pageQuery</code> أو من خلال استعلام ساكن ضمن المكوّن.
ستجد البيانات الوصفية (الاسم والوصف وغيرها) للموقع المبني باستخدام Gatsby ضمن الملف <code>gatsby-config.js</code> وتُستعرض بعد ذلك من قبل واجهة GraphQL البرمجية التي تتعامل معها من خلال <code>pageQuery</code> أو من خلال استعلام ساكن ضمن المكوّن.


لكن يُفضَّل في Next.js إنشاء ملف تهيئة يُشابه في محتواه الشيفرة التالية<u>؛</u> ومن ثم تستطيع إدراج هذه الملف في أي مكان دون الحاجة لاستخدام GraphQL للولوج إلى البيانات الوصفية للموقع:<syntaxhighlight lang="javascript">
لكن يُفضَّل في Next.js إنشاء ملف تهيئة يُشابه في محتواه الشيفرة التالية؛ ومن ثم تستطيع إدراج هذه الملف في أي مكان دون الحاجة لاستخدام GraphQL للولوج إلى البيانات الوصفية للموقع:<syntaxhighlight lang="javascript">
// src/config.js
// src/config.js


سطر 258: سطر 258:


=== تحسين نتائج البحث في محركات البحث ===
=== تحسين نتائج البحث في محركات البحث ===
تستخدم معظم أمثلة Gatsby العنصر <code>react-helmet</code> للمساعدة في إضافة بيانات وصفية <code>meta</code> لأغراض تحسين نتيجة ظهور الموقع في محركات البحث SEO. تستخدم Next.js في المقابل المكوّن [[Next.js/next head|<code>next/head</code>]] لإضافة هذه البيانات إلى العنصر <code></ head></code>. إليك مثالًا عن مكوّن SEO للغة Gatsby:<syntaxhighlight lang="javascript">
تستخدم معظم أمثلة Gatsby العنصر <code>react-helmet</code> للمساعدة في إضافة بيانات وصفية <code>meta</code> لأغراض تحسين نتيجة ظهور الموقع في محركات البحث SEO. تستخدم Next.js في المقابل المكوّن [[Next.js/next head|<code>next/head</code>]] لإضافة هذه البيانات إلى العنصر <code></ head></code>. إليك مثالًا عن مكوّن SEO في Gatsby:<syntaxhighlight lang="javascript">
// src/components/seo.js
// src/components/seo.js


سطر 343: سطر 343:
وهي الخطوة الأولى في عملية الانتقال وعليك تنفيذ ما يلي:
وهي الخطوة الأولى في عملية الانتقال وعليك تنفيذ ما يلي:


* إزالة الحزمة (ابق فقط <code>react</code> و <code>react-dom</code>). إن كنت تستخدم React Router يمكنك إزالة <code>react-router-dom</code> أيضًا.
* إزالة حزم <code>react</code> (ابق فقط <code>react</code> و <code>react-dom</code>). إن كنت تستخدم React Router يمكنك إزالة <code>react-router-dom</code> أيضًا.
* ثبِّت <code>next</code>.
* ثبِّت <code>next</code>.
* أضف الأوامر المتعلقة بلغة Next.js إلى <code>scripts</code> وأولها <code>next dev</code> الذي يشغّل خادم التطوير على العنوان <code>localhost:3000</code>. أما ثانيها فهو <code>next build</code> و <code>next start</code> لإنشاء وتشغيل نسخة الإنتاج.
* أضف أوامر Next.js إلى <code>scripts</code> وأولها <code>next dev</code> الذي يشغّل خادم التطوير على العنوان <code>localhost:3000</code>. أما ثانيها فهو <code>next build</code> و <code>next start</code> لإنشاء وتشغيل نسخة الإنتاج.


إليك مثالًا عن <code>package.json</code>:<syntaxhighlight lang="json">
إليك مثالًا عن <code>package.json</code>:<syntaxhighlight lang="json">
سطر 362: سطر 362:
</syntaxhighlight>
</syntaxhighlight>


=== الموجودات الساكنة والخرج المُصرَّف ===
=== الأصول الساكنة والخرج المُصرَّف ===
تستخدم Create React App المجلد <code>public</code> لوضع ملفات HTML التي تُمثِّل نقاط دخول إلى التطبيق والموجودات الساكنة بينما تستخدم Next.js هذا المجلد لوضع الموجودات الساكنة فقط. إليك خطوات الانتقال في هذه المرحلة:
تستخدم Create React App المجلد <code>public</code> لوضع ملفات HTML التي تُمثِّل نقاط دخول إلى التطبيق والموجودات الساكنة بينما تستخدم Next.js هذا المجلد لوضع الأصول الساكنة static assests فقط. إليك خطوات الانتقال في هذه المرحلة:


* انقل أية صور أو خطوط أو أية موجودات ساكنة أخرى إلى المجلد
* انقل أية صور أو خطوط أو أية الأصول أو موجودات ساكنة أخرى إلى المجلد <code>public</code>.
* حوّل الملف <code>index.html</code> (نقطة الدخول إلى التطبيق) إلى Next.js، وينبغي نقل أية شيفرات ضمن العنصر إلى [[Next.js/custom document|مستند مخصص <code>document.js_</code>]]، وكذلك أية تخطيطات layouts مشتركة بين الصفحات إلى [[Next.js/custom app|تطبيقات APP مخصصة]].
* حوّل الملف <code>index.html</code> (نقطة الدخول إلى التطبيق) إلى Next.js، وينبغي نقل أية شيفرات <code><head></code> ضمنه إلى [[Next.js/custom document|مستند مخصص <code>document.js_</code>]]، وكذلك أية تخطيطات layouts مشتركة بين الصفحات إلى [[Next.js/custom app|تطبيق APP مخصص]].
* أضف <code>next.</code> إلى <code>gitignore.</code>.
* أضف <code>next.</code> إلى <code>gitignore.</code>.


سطر 379: سطر 379:
* أما الوجهات التي تتطلب مساراتها محتوى ديناميكي (مثل <code>blog/:slug/</code>)، بإمكانك استخدام الوجهات الديناميكية في Next.js (مثل <code>pages/blog/[slug].js</code>). يمكن الوصول إلى قيمة <code>slug</code> من خلال معامل استعلام. إذ يمكن مثلًا الوصول إلى المنشور <code>blog/first-post/</code> انطلاقًا من القالب <code>pages/blog/[slug].js</code> من خلال كائن الاستعلام <code>{ 'slug': 'first-post' }</code>.
* أما الوجهات التي تتطلب مساراتها محتوى ديناميكي (مثل <code>blog/:slug/</code>)، بإمكانك استخدام الوجهات الديناميكية في Next.js (مثل <code>pages/blog/[slug].js</code>). يمكن الوصول إلى قيمة <code>slug</code> من خلال معامل استعلام. إذ يمكن مثلًا الوصول إلى المنشور <code>blog/first-post/</code> انطلاقًا من القالب <code>pages/blog/[slug].js</code> من خلال كائن الاستعلام <code>{ 'slug': 'first-post' }</code>.


=== التنسيق ===
تقدم Next.js [[Next.js/built in css support|دعمًا مدمجًا لتنسيق CSS و SaSS و CSS-in-JS]]. كما يسمح Create React App بإدراج ملفات <code>css.</code> مباشرة ضمن المكوّنات. تسمح Next.js بنفس هذا الأسلوب أيضًا، لكن لا بد أن تكون هذه الملفات [[Next.js/built in css support|وحدات تنسيق CSS]]. أما بالنسبة للتنسيقات العامة، ستحتاج إلى [[Next.js/custom app|تطبيق App مخصص]] لإضافتها.
تقدم Next.js [[Next.js/built in css support|دعمًا مدمجًا لتنسيق CSS و SaSS و CSS-in-JS]]. كما يسمح Create React App بإدراج ملفات <code>css.</code> مباشرة ضمن المكوّنات. تسمح Next.js بنفس هذا الأسلوب أيضًا، لكن لا بد أن تكون هذه الملفات [[Next.js/built in css support|وحدات تنسيق CSS]]. أما بالنسبة للتنسيقات العامة، ستحتاج إلى [[Next.js/custom app|تطبيق App مخصص]] لإضافتها.


=== الولوج الآمن إلى واجهة التطبيقات البرمجية ===
=== الولوج الآمن إلى واجهة الويب البرمجية ===
يمكن الوصول إلى الواجهة <code>window</code> أو<code>localStorage</code> أو <code>navigator</code> وغيرها من واجهات ويب البرمجية مباشرة عبر التطبيقات التي تُصيَّر من جانب العميل. لكن طالما أن Next.js تستخدم التصيير المسبق، لا بد من الوصول إلى تلك الواجهات بطريقة آمنة عندما يكون المستخدم في الواجهة الأمامية. تسمح الشيفرة التالية مثلًا بالوصول إلى الواجهة <code>window</code> من جهة العميل فقط (من الواجهة الأمامية):<syntaxhighlight lang="javascript">
يمكن الوصول إلى الواجهة <code>window</code> أو <code>localStorage</code> أو <code>navigator</code> وغيرها من واجهات ويب البرمجية مباشرة عبر التطبيقات التي تُصيَّر من جانب العميل. لكن طالما أن Next.js تستخدم التصيير المسبق، لا بد من الوصول إلى تلك الواجهات بطريقة آمنة عندما يكون المستخدم في الواجهة الأمامية. تسمح الشيفرة التالية مثلًا بالوصول إلى الواجهة <code>window</code> من جهة العميل فقط (من الواجهة الأمامية):<syntaxhighlight lang="javascript">
if (typeof window !== 'undefined') {
if (typeof window !== 'undefined') {
   //الآن window يمكنك الوصول إلى `
   //الآن window يمكنك الوصول إلى `
سطر 418: سطر 419:
</syntaxhighlight>
</syntaxhighlight>


=== متغيّرات البيئة ===
=== متغيرات البيئة ===
تدعم [[Next.js/environment variables|متغيرات البيئة]] <code>env.</code> كما يفعل Create React App، ويكمن الفرق الأساسي بينهما هو البادئة التي تكشف متغير البيئة لجانب العميل.
تدعم [[Next.js/environment variables|متغيرات البيئة]] <code>env.</code> كما يفعل Create React App، ويكمن الفرق الأساسي بينهما هو البادئة التي تكشف متغير البيئة لجانب العميل.


* حوّل بادئات متغيرات البيئة من <code>_REACT_APP</code> إلى <code>_NEXT_PUBLIC</code>.
* حوّل بادئات متغيرات البيئة من <code>_REACT_APP</code> إلى <code>_NEXT_PUBLIC</code>.
* تتاح متغيرات البيئة للاستخدام أثناء بناء التطبيق وعند طلب وجهات API>
* تتاح متغيرات البيئة للاستخدام أثناء بناء التطبيق وعند طلب وجهات API.


=== تحسين نتائج البحث في محركات البحث ===
=== تحسين نتائج البحث في محركات البحث ===
تستخدم معظم أمثلة Create React App العنصر <code>react-helmet</code> للمساعدة في إضافة بيانات وصفية <code>meta</code> لأغراض تحسين نتيجة ظهور الموقع في محركات البحث SEO. تستخدم Next.js في المقابل المكوّن [[Next.js/next head|<code>next/head</code>]] لإضافة هذه البيانات إلى العنصر <code></ head></code>. إليك مثالًا عن مكوّن SEO للغة Create React App:<syntaxhighlight lang="javascript">
تستخدم معظم أمثلة Create React App العنصر <code>react-helmet</code> للمساعدة في إضافة بيانات وصفية <code>meta</code> لأغراض تحسين نتيجة ظهور الموقع في محركات البحث SEO. تستخدم Next.js في المقابل المكوّن [[Next.js/next head|<code>next/head</code>]] لإضافة هذه البيانات إلى العنصر <code></ head></code>. إليك مثالًا عن مكوّن SEO في تطبيق Create React App:<syntaxhighlight lang="javascript">
// src/components/seo.js
// src/components/seo.js


سطر 520: سطر 521:


=== التطبيقات المدارة ذاتيًا ===
=== التطبيقات المدارة ذاتيًا ===
إن كنت تمتلك تطبيق Create React App مُدار ذاتيًا (أو مفصول عن إطار العمل ejeected)، إليك بعض النقاط التي ينبغي أخذها بعين الاعتبار:
إن كنت تمتلك تطبيق Create React App مُدار ذاتيًا (أو مفصول ejected باستعمال الأمر <code>npm run eject</code> وتديره أنت ذاتيًا بكامل ضبطه وخياراته)، إليك بعض النقاط التي ينبغي أخذها بعين الاعتبار:


* إن كان لديك ملف مخصص مهيأ ليضم محمِّلات CSS أو Sass أو غيرها من الموجودات فهذه المحملات مدمجة في Next.js.
* إن كان لديك ملف مخصص مهيأ ليضم محمِّلات CSS أو Sass أو غيرها من الموجودات فهذه المحملات مدمجة في Next.js.
* إن أضفت بنفسك [[Next.js/supported browsers features|ميزات JavaScript جديدة]] (كالسَلسَلة الاختيارية) أو شيفرات مواءمة، فتحقق مما هو مدمج بالفعل في Next.js.
* إن أضفت بنفسك [[Next.js/supported browsers features|ميزات JavaScript جديدة]] (كالسَلسَلة الاختيارية) أو [[Next.js/supported browsers features|شيفرات مواءمة]] Polyfills، فتحقق مما هو مدمج بالفعل في Next.js.
* إن كان لديك إعدادات مخصصة لفصل الشيفرات Next.js، يمكنك إزالتها لأن Next.js تمتلك آلية فصل شيفرات تلقائية مبنية على أساس الصفحات.
* إن كان لديك إعدادات مخصصة لفصل الشيفرات Next.js، يمكنك إزالتها لأن Next.js تمتلك آلية فصل شيفرات تلقائية مبنية على أساس الصفحات.
* يمكنك [[Next.js/customizing postcss config|تخصيص إعدادات PostCSS]] في Next.js دون الحاجة إلى فصل التطبيق عن منصة العمل.
* يمكنك [[Next.js/customizing postcss config|تخصيص إعدادات PostCSS]] في Next.js دون الحاجة إلى فصل التطبيق عن منصة العمل.
سطر 556: سطر 557:
   )
   )
}
}
</syntaxhighlight>تمتلك معظم تطبيقات React التي تستخدم React Router ملف عال المستوى يحتوي على قائمة بكل الوجهات. إليك مثالًا:<syntaxhighlight lang="javascript">
</syntaxhighlight>تمتلك معظم تطبيقات React التي تستخدم React Router ملفًا عال المستوى يحتوي على قائمة بكل الوجهات. إليك مثالًا:<syntaxhighlight lang="javascript">
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'


سطر 582: سطر 583:
* <code>pages/index.js</code> → <code>/</code>
* <code>pages/index.js</code> → <code>/</code>


== الوجهات المتداخلة ==
=== الوجهات المتداخلة ===
 
تُصيّر الوجهات مثل <code>blog/my-post/</code> في الشيفرة التالية إلى مكوِّن <code>Post</code>. فإن لم تكن هناك كتلة ديناميكية <code>slug</code> تحدد هوية المنشور، سيصيّر قائمة المنشورات بأكملها:<syntaxhighlight lang="javascript">
تُصيّر الوجهات مثل <code>blog/my-post/</code> في الشيفرة التالية إلى مكوِّن <code>Post</code>. فإن لم تكن هناك كتلة ديناميكية <code>slug</code> تحدد هوية المنشور، سيصيّر قائمة المنشورات بأكملها:<syntaxhighlight lang="javascript">
import {
import {
سطر 614: سطر 616:
   return <h1>Post Slug: {slug}</h1>
   return <h1>Post Slug: {slug}</h1>
}
}
</syntaxhighlight>تستخدم Next.js الصيغة <code>[slug:]</code> ضمن اسم الملف للتوجه الديناميكي بدلًا من استخدامها ضمن المكوّن <code>Route</code>. وبالإمكان الانتقال إلى Next.js بإنشاء ملفين جديدين الأول <code>pages/blog/[slug].js</code> (ليعرض كل الصفحات) والآخر <code>pages/blog/[slug].js</code> (لعرض منشورات مفردة):<syntaxhighlight lang="javascript">
</syntaxhighlight>تستخدم Next.js الصيغة <code>[slug:]</code> ضمن اسم الملف للتوجه الديناميكي بدلًا من استخدام <code>slug:</code> ضمن المكوّن <code>Route</code>. وبالإمكان الانتقال إلى Next.js بإنشاء ملفين جديدين الأول <code>pages/blog/[slug].js</code> (ليعرض كل الصفحات) والآخر <code>pages/blog/[slug].js</code> (لعرض منشورات مفردة):<syntaxhighlight lang="javascript">
// pages/blog/index.js
// pages/blog/index.js


سطر 646: سطر 648:
راجع صفحة [[Next.js/dynamic import|الإدراج الديناميكي]] لمعلومات أوفى.
راجع صفحة [[Next.js/dynamic import|الإدراج الديناميكي]] لمعلومات أوفى.


=== استعادة وضع التمرير ===
=== استعادة موضع التمرير ===
تقدم Next.js دعمًا مدمجًا لاستعادة وضع التمرير scroll restoration، وبالتالي يمكنك إزالة أية مكوّنات <code>ScrollToTop</code> خاصة قد عرّفتها.
تقدم Next.js دعمًا مدمجًا لاستعادة موضع التمرير scroll restoration، وبالتالي يمكنك إزالة أية مكوّنات <code>ScrollToTop</code> خاصة قد عرّفتها.


إن السلوك الافتراضي للمكونين <code>next/link</code> و <code>next/router</code> هو تمرير المحتوى حتى أعلى الصفحة، لكن بإمكانك أيضًا تعطيل هذا السلوك إن أردت.
إن السلوك الافتراضي للمكونين <code>next/link</code> و <code>next/router</code> هو تمرير المحتوى حتى أعلى الصفحة، لكن بإمكانك أيضًا تعطيل هذا السلوك إن أردت.
== أمثلة ==
* [https://github.com/vercel/next.js/tree/canary/examples/rewrites\ Rewrites]
* [https://github.com/vercel/next.js/tree/canary/examples/redirects Redirects]
* [https://github.com/vercel/next.js/tree/canary/examples/with-zones Multi-Zones]


== اقرأ أيضًا ==
== اقرأ أيضًا ==


* ألق نظرة على هذا المثال المخصص على Github لتتعرف على تفاصيل أكثر عن نقل تطبيق Gatsby إلى Next.js.
*[[Next.js/Routing|تعلم التوّجه في Next.js]]
* [[Next.js/Routing|تعلم التوّجه في Next.js]].
*[[Next.js/Routing|الوجهات الديناميكية في Next.js]]
* [[Next.js/Routing|الوجهات الديناميكية في Next.js]].
*[[Next.js/next link|التنقل عبر الواجهة الأمامية في Next.js]]
* [[Next.js/next link|التنقل عبر الواجهة الأمامية في Next.js]].


== المصادر ==
== المصادر ==


* صفحات [https://nextjs.org/docs/migrating/ Migrating to Next.js] من توثيق Next.js الرسمي
* صفحات [https://nextjs.org/docs/migrating/ Migrating to Next.js] من توثيق Next.js الرسمي
[[تصنيف:Next.js|{{SUBPAGENAME}}]]

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

صُمِّمت Next.js لكي يجري تبنيها تدريجيًا، إذ ستكون قادرًا على متابعة العمل على شيفرة جاهزة حالية وإضافة المقدار الذي تريده من شيفرة React. فإن بدأت بكمية صغيرة من الشيفرة ووسعتها تدريجيًا بإضافة صفحات جديدة، سيسهل ذلك عليك تبني Next.js في مشاريعك وتجنب إعادة كتابة كل شيء بالكامل.

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

المسارات الفرعية Subpath

تقتضي الاستراتيجية الأولى بتهيئة الخادم أو الخادم الوكيل لوضع كل ما يتعلق بتطبيق Next.js في نفس المسار الفرعي (ضمن مجلد فرعي). فقد يكون موقعك الإلكتروني مثلًا example.com ومن ثم تهيئ المسار الفرعي example.com/store على الخادم ليضم تطبيق لمتجر إلكتروني.

بإمكانك تهيئة أصول assets وروابط تطبيق Next.js لتعمل تلقائيًا عند طلب الوجهة store/، وذلك باستخدام basePath. وبما أن كل صفحة من صفحات Next.js هي وجهة قائمة بنفسها، يمكنك الوصول إلى الصفحة pages/products.js مثلًا عبر المسار example.com/store/products.

// next.config.js

module.exports = {
  basePath: '/store',
}

الدالة rewrites

تقتضي الاستراتيجية الثانية إنشاء تطبيق Next.js جديد يشير إلى عنوان URL الجذري للنطاق domain الذي تستخدمه. استخدم بعد ذلك الدالة rewrites ضمن ملف التهيئة لكي تُحوَّل بعض المسارات إلى التطبيق الموجود.


لنفرض مثلًا أنك أنشأت تطبيق Next.js كي يُخدّم عبر النطاق example.com وله ملف التهيئة next.config.js. عندها ستتعامل Next.js مع الصفحات التي أضفتها إلى تطبيقك (مثل about/ إن أضفت pages/about.js)، بينما ستحوّل أية طلبات أخرى (مثل dashboard/) إلى proxy.example.com.

ملاحظة: إن كنت تستعمل fallback: true/'blocking'‎ في getStaticPaths، فلن يعمل الالتقاط الكامل catch-all ضمن rewrites المُعرف في الملف next.config.js إذ ستلتقطها getStaticPaths.

// next.config.js

module.exports = {
  async rewrites() {
    return {
        
      //(بما في ذلك المسارت الديناميكة) Next.js بعد التحقق من كل صفحات
      // والملفات الساكنة سنحوّل أي طلبات أخرى
      fallback: [
        {
          source: '/:path*',
          destination: `https://proxy.example.com/:path*`,
        },
      ],
    }
    //في الإصدارات مادون 10.1 rewrite يمكنك استخدام الدالة غير الفعالة 
    return [
      // لابد من تعريف دالة غير فعالة لتحرض عملية التحقق
      // من كل الصفحات الساكنة قبل أن نحاول تحويل المسار
      {
        source: '/:path*',
        destination: '/:path*',
      },
      {
        source: '/:path*',
        destination: `https://proxy.example.com/:path*`,
      },
    ]
  },
}

ملاحظة: إن كنت تنتقل تدريجيا إلى الوجهات الديناميكية مثل ‎[slug] وكنت تستعمل fallback: true أو fallback: 'blocking'‎ مع rewrite، فتأكد من أن تشمل حالة عدم العثور على صفحة page not found، إذ عندما تلتقط Next.js الوجهات الديناميكية فإنها تتوقف عن التحقق من أي وجهات أخرى. استعمال notFound: true في getStaticProps سيعيد صفحة 404 دون تطبيق rewrite، فإن لم تكن ترغب بذلك، يمكنك استعمال getServerSideProps مع ترويسة التحكم بالتخزين المؤقت stale-while-revalidate عند إعادة الخاصيات props وبعدها يمكنك إعادة التوجيه proxy يدويًا إلى الواجهة الخلفية الحالية باستعمال أدوات مثل http-proxy بدلًا من إعادة notFound: true.

واجهات أمامية مُصغرة مع مستودعات مفردة ونطاقات فرعية

تجعل Next.js و Vercel عملية بناء الواجهات الأمامية المصغّرة أو المجزّأة micro-frontends ونشرها إلى مستودع مفرد Monorepo أمرًا مباشرًا وبسيطًا. يسمح لك ذلك باستخدام النطاقات الفرعية لتبنّي تطبيقات جديدة تدريجيًا. ومن مزايا استخدام الواجهة الأمامية المصغّرة:

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

حالما تنهي تهيئة مستودعك المفرد، ادفع بالتغييرات إلى مستودع Git كالعادة وسترى أن حمولتك قد نُشرت ضمن مشاريع Vercel المرتبطة بها.

الانتقال من Gatesby

يساعدك هذا الدليل في نقل تطبيقك Gatsby إلى تطبيق Next.js؛ إذ يسمح لك الانتقال إلى Next.js أن:

سنحاول الآن إنجاز عملية الإنتقال خطوة خطوة

تحديث الملف package.json والاعتماديات

وهي الخطوة الأولى في عملية الانتقال وعليك تنفيذ ما يلي:

  • إزالة كل الحزم المتعلقة ب Gatsby (ابق فقط react و react-dom)
  • ثبِّت next.
  • أضف الأوامر Next.js إلى scripts وأولها next dev الذي يشغّل خادم التطوير على العنوان localhost:3000. أما ثانيها فهو next build و next start لإنشاء وتشغيل نسخة الإنتاج.

إليك مثالًا عن package.json:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  }
}

الأصولو الساكنة والخرج المُصرَّف

تستخدم Gatsby المجلد public لوضع ملفات الخرج المصرَّفة بينما تستخدم Next.js هذا المجلد لوضع الأصول الساكنة static assets. إليك خطوات الانتقال في هذه المرحلة:

  • أزل الإشارة إلى المجلدين /cache. و public من الملف gitignore. واحذف المجلدين.
  • غيّر اسم المجلد static إلى public.
  • أضف next. إلى gitignore..

إنشاء الوجهات Routes

تدعم كلا Gatsby و Next المجلد pages الذي يستخدم أسلوب توجيه يعتمد على نظام الملفات. تستخدم المجلد src/pages الذي تدعمه أيضًا Next.js. تُنشئ Gatsby الوجهات الديناميكية باستخدام الواجهة البرمجية createPages ضمن الملف gatsby-node.js. ويمكنك في Next استخدام الوجهات الديناميكية ضمن المجلد pages للحصول على نفس التأثير. وبدلًا من وجود مجلد بالاسم template، يمكنك استخدام مكوّنات React ضمن ملف الوجهة الديناميكية:

  • في Gatsby: أنشئ مسارات ديناميكية لكل منشور مثلًا باستخدام الواجهة createPages ومن ثم أنشئ ملفًا يمثل قالبًا لهذه المنشورات ضمن src/templates/blog-post.js.
  • في Next: أنشئ المسارات الديناميكية على الشكل pages/blog/[slug].js لتمثل قالبًا للمنشورات. يمكن الوصول إلى قيمة slug من خلال معامل استعلام. إذ يمكن مثلًا الوصول إلى المنشور blog/first-post/ انطلاقًا من القالب pages/blog/[slug].js من خلال كائن الاستعلام { 'slug': 'first-post' }.

تنسيق الصفحات

تُدرج Gatsby تنسيقات CSS العامة في الملف gatsby-browser.js، لكن لا بد من إنشاء تطبيق app.js_ مخصص للتنسيقات العامة في Next.js. عند الانتقال إلى Next.js بإمكانك نسخ التنسيقات المُدرجة مباشرة وتحديث المسارات النسبية إن اقتضى الأمر. وتذكر أن Next.js تقدم دعمًا مدمجًا لتنسيق CSS.

الروابط

للمكوّن Link في Gatsby ونظيره Link في Next.js واجهتان برمجيتان تختلفان اختلافًا طفيفًا:

// Gatsby

import { Link } from 'gatsby'

export default function Home() {
  return <Link to="/blog">blog</Link>
}
// Next.js

import Link from 'next/link'

export default function Home() {
  return (
    <Link href="/blog">
      <a>blog</a>
    </Link>
  )
}

حدِّث أية عبارت إدراج مختلفة، ثم بدّل to إلى href وأضف العنصر <a> ضمن العنصر <link>.

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

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

تستخدم Gatsby الدالة graphql لاستعلام البيانات في صفحات الموقع بما فيها البيانات المحلية والبعيدة ومعلومات التهيئة الخاصة بالموقع، كما تسمح بإنشاء صفحات ساكنة فقط. أما في Next.js، بإمكانك اختيار استراتيجية إحضار البيانات الخاصة بكل صفحة. إذ تسمح لك الدالة getServerSideProps مثلًا بتنفيذ التصيير من جانب الخادم، بينما بإمكانك تصدير الدالتين getStaticProps / getStaticPaths ضمن الصفحة لتوليد صفحات ساكنة بدلًا من تنفيذ pageQuery. إليك مثالًا:

// src/pages/[slug].js
// remark-html و remark ثبِّت 
import { remark } from 'remark'
import html from 'remark-html'
import { getPostBySlug, getAllPosts } from '../lib/blog'

export async function getStaticProps({ params }) {
  const post = getPostBySlug(params.slug)
  const markdown = await remark()
    .use(html)
    .process(post.content || '')
  const content = markdown.toString()

  return {
    props: {
      ...post,
      content,
    },
  }
}

export async function getStaticPaths() {
  const posts = getAllPosts()

  return {
    paths: posts.map((post) => {
      return {
        params: {
          slug: post.slug,
        },
      }
    }),
    fallback: false,
  }
}

سترى عادة ملحقات plugins في Gatsby لقراءة منظومة الملفات gatsby-source-filesystem أو التعامل مع تنسيق Markdown من خلال gatsby-transformer-remark وغيرها. فالمثال النموذجي الأكثر شعبية لمبتدئي تطبيقات المنشورات، قد استخدم 15 حزمة Gatsby خاصة. تأخذ Next في المقابل نهجًا آخر، إذ تُضمِّن الميزات كثيرة الاستعمال مباشرة ضمن إطار العمل، وتمنح المستخدم تحكمًا كاملًا في دعم التطبيق بحزم خارجية. فبدلًا من فصل شيفرة القراءة من منظومة الملفات ضمن ملحق، بإمكانك استخدام حزمة Node.js الأصلية fs ضمن الدالتين getStaticProps / getStaticPaths لقراءة منظومة الملفات:

// src/lib/blog.js
//date-fns و gray-matter ثبِّت 
import matter from 'gray-matter'
import { parseISO, format } from 'date-fns'
import fs from 'fs'
import { join } from 'path'
//`src/content/blog` إلى markdown أضف ملفات 
const postsDirectory = join(process.cwd(), 'src', 'content', 'blog')

export function getPostBySlug(slug) {
  const realSlug = slug.replace(/\.md$/, '')
  const fullPath = join(postsDirectory, `${realSlug}.md`)
  const fileContents = fs.readFileSync(fullPath, 'utf8')
  const { data, content } = matter(fileContents)
  const date = format(parseISO(data.date), 'MMMM dd, yyyy')

  return { slug: realSlug, frontmatter: { ...data, date }, content }
}

export function getAllPosts() {
  const slugs = fs.readdirSync(postsDirectory)
  const posts = slugs.map((slug) => getPostBySlug(slug))

  return posts
}

مكون الصور وتحسين الصور

تمتلك Next.js مكوِّن صور مدمج وطريقة تحسين مدمجة للصور. إذ يُعد المكوِّن next/image امتدادًا لعنصر الصورة <img> في HTML، وقد طوّر ليلائم مواقع الويب الحديثة.

يتيح لك التحسين التقائي للصور إعادة تحجيم الصورة وتحسينها وتقديمها بامتدادات حديثة مثل WebP عندما يدعمها المتصفح. يقلل ذلك من الدفع بصورة كبيرة إلى أجهزة لها نافذة عرض صغيرة، كما يسمح لـ Next.js بالتبني التلقائي لتنسيقات الصور المستقبلية، وتقديمها للمتصفح الذي يدعمها.

الإنتقال بالصور من Gatsby

تعمل Next.js على تحسين الصورة عند الطلب بدلًا من تحسينها أثناء بناء التطبيق. وعلى خلاف مولِّدات المواقع الساكنة والحلول الساكنة فقط، لن يزيد ذلك زمن بناء التطبيق سواءً حمّلت 10 صور أو 10 ملايين صورة. ويعني أنه بإمكانك إزالة ملحقات Gatsby الشائعة مثل:

  • gatsby-image
  • gatsby-transformer-sharp
  • gatsby-plugin-sharp

استخدم بدلًا من ذلك المكوّن next/image والتحسين التلقائي للصورة.

لا يُدعم المُحمّل الافتراضي للمكون next/image عند استخدام next export، لكن ستعمل خيارات أخرى.

import Image from 'next/image'
import profilePic from '../public/me.png'

export default function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src={profilePic}
        alt="Picture of the author"
        //Gatsby في "fluid" الخيار "responsive" يُشابه 
        //Gatsby  بأعظم عرض في"fluid" الخيار "intrinsic" يُشابه 
        //Gatsby في ""fixed" الخيار "fixed" يُشابه 
        layout="responsive"
        //Gatsby في "blur-up" اختياري، ويشابه 
        placeholder="blur"
        //Gatsby GraphQL في "width" اختياري، ويشابه 
        width={500}
        //Gatsby GraphQL في "height" اختياري، ويشابه 
        height={500}
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}

تهيئة الموقع

ستجد البيانات الوصفية (الاسم والوصف وغيرها) للموقع المبني باستخدام Gatsby ضمن الملف gatsby-config.js وتُستعرض بعد ذلك من قبل واجهة GraphQL البرمجية التي تتعامل معها من خلال pageQuery أو من خلال استعلام ساكن ضمن المكوّن.

لكن يُفضَّل في Next.js إنشاء ملف تهيئة يُشابه في محتواه الشيفرة التالية؛ ومن ثم تستطيع إدراج هذه الملف في أي مكان دون الحاجة لاستخدام GraphQL للولوج إلى البيانات الوصفية للموقع:

// src/config.js

export default {
  title: 'Starter Blog',
  author: {
    name: 'Lee Robinson',
    summary: 'who loves Next.js.',
  },
  description: 'A starter blog converting Gatsby -> Next.',
  social: {
    twitter: 'leeerob',
  },
}

تحسين نتائج البحث في محركات البحث

تستخدم معظم أمثلة Gatsby العنصر react-helmet للمساعدة في إضافة بيانات وصفية meta لأغراض تحسين نتيجة ظهور الموقع في محركات البحث SEO. تستخدم Next.js في المقابل المكوّن next/head لإضافة هذه البيانات إلى العنصر </ head>. إليك مثالًا عن مكوّن SEO في Gatsby:

// src/components/seo.js

import { Helmet } from 'react-helmet'

export default function SEO({ description, title, siteTitle }) {
  return (
    <Helmet
      title={title}
      titleTemplate={siteTitle ? `%s | ${siteTitle}` : null}
      meta={[
        {
          name: `description`,
          content: description,
        },
        {
          property: `og:title`,
          content: title,
        },
        {
          property: `og:description`,
          content: description,
        },
        {
          property: `og:type`,
          content: `website`,
        },
        {
          name: `twitter:card`,
          content: `summary`,
        },
        {
          name: `twitter:creator`,
          content: twitter,
        },
        {
          name: `twitter:title`,
          content: title,
        },
        {
          name: `twitter:description`,
          content: description,
        },
      ]}
    />
  )
}

وهذا هو المثال ذاته باستخدام Next.js بما في ذلك القراءة من ملف إعدادات الموقع:

// src/components/seo.js

import Head from 'next/head'
import config from '../config'

export default function SEO({ description, title }) {
  const siteTitle = config.title

  return (
    <Head>
      <title>{`${title} | ${siteTitle}`}</title>
      <meta name="description" content={description} />
      <meta property="og:type" content="website" />
      <meta property="og:title" content={title} />
      <meta property="og:description" content={description} />
      <meta property="og:site_name" content={siteTitle} />
      <meta property="twitter:card" content="summary" />
      <meta property="twitter:creator" content={config.social.twitter} />
      <meta property="twitter:title" content={title} />
      <meta property="twitter:description" content={description} />
    </Head>
  )
}

الانتقال من Create React App

يساعدك هذا الدليل في نقل تطبيقك من Create React App إلى تطبيق Next.js؛ إذ يسمح لك ذلك أن:

سنحاول الآن إنجاز عملية الإنتقال خطوة خطوة.

تحديث الملف package.json والاعتماديات

وهي الخطوة الأولى في عملية الانتقال وعليك تنفيذ ما يلي:

  • إزالة حزم react (ابق فقط react و react-dom). إن كنت تستخدم React Router يمكنك إزالة react-router-dom أيضًا.
  • ثبِّت next.
  • أضف أوامر Next.js إلى scripts وأولها next dev الذي يشغّل خادم التطوير على العنوان localhost:3000. أما ثانيها فهو next build و next start لإنشاء وتشغيل نسخة الإنتاج.

إليك مثالًا عن package.json:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  }
}

الأصول الساكنة والخرج المُصرَّف

تستخدم Create React App المجلد public لوضع ملفات HTML التي تُمثِّل نقاط دخول إلى التطبيق والموجودات الساكنة بينما تستخدم Next.js هذا المجلد لوضع الأصول الساكنة static assests فقط. إليك خطوات الانتقال في هذه المرحلة:

  • انقل أية صور أو خطوط أو أية الأصول أو موجودات ساكنة أخرى إلى المجلد public.
  • حوّل الملف index.html (نقطة الدخول إلى التطبيق) إلى Next.js، وينبغي نقل أية شيفرات <head> ضمنه إلى مستند مخصص document.js_، وكذلك أية تخطيطات layouts مشتركة بين الصفحات إلى تطبيق APP مخصص.
  • أضف next. إلى gitignore..

وسنناقش لاحقًا موضوع التنسيق.

إنشاء الوجهات والروابط

قد تستخدم المكتبة React Router في تطبيقات Create React App، لكن بدلًا من استخدام مكتبة من طرف آخر، تقدم طريقة Next.js آلية توجه مدمجة مبنية على نظام الملفات.

  • أنشئ المجلد pages في جذر المشروع.
  • انقل الملف src/App.js ليصبح pages/index.js. يمثل هذا الملف الصفحة الرئيسية لتطبيقك. ادمج هذا الملف مع الشيفرة التي تُستخدم لعرض وجهة الصفحة الرئيسية في تطبيق Create React App.
  • حوّل كل المكوّنات Route إلى ملفات جديدة في المجلد pages.
  • أما الوجهات التي تتطلب مساراتها محتوى ديناميكي (مثل blog/:slug/)، بإمكانك استخدام الوجهات الديناميكية في Next.js (مثل pages/blog/[slug].js). يمكن الوصول إلى قيمة slug من خلال معامل استعلام. إذ يمكن مثلًا الوصول إلى المنشور blog/first-post/ انطلاقًا من القالب pages/blog/[slug].js من خلال كائن الاستعلام { 'slug': 'first-post' }.

التنسيق

تقدم Next.js دعمًا مدمجًا لتنسيق CSS و SaSS و CSS-in-JS. كما يسمح Create React App بإدراج ملفات css. مباشرة ضمن المكوّنات. تسمح Next.js بنفس هذا الأسلوب أيضًا، لكن لا بد أن تكون هذه الملفات وحدات تنسيق CSS. أما بالنسبة للتنسيقات العامة، ستحتاج إلى تطبيق App مخصص لإضافتها.

الولوج الآمن إلى واجهة الويب البرمجية

يمكن الوصول إلى الواجهة window أو localStorage أو navigator وغيرها من واجهات ويب البرمجية مباشرة عبر التطبيقات التي تُصيَّر من جانب العميل. لكن طالما أن Next.js تستخدم التصيير المسبق، لا بد من الوصول إلى تلك الواجهات بطريقة آمنة عندما يكون المستخدم في الواجهة الأمامية. تسمح الشيفرة التالية مثلًا بالوصول إلى الواجهة window من جهة العميل فقط (من الواجهة الأمامية):

if (typeof window !== 'undefined') {
  //الآن window يمكنك الوصول إلى `
}

ومن الطرق المستحسنة للوصول الآمن إلى الواجهات هو استخدام الخطاف useEffect والذي يُنفَّذ فقط في جانب العميل:

import { useEffect } from 'react'

useEffect(() => {
  //الآن window يمكنك الوصول إلى `
}, [])

مكوّن الصور وتحسين الصور

تمتلك Next.js ابتداءً من الإصدار 10.0.0 مكوِّن صور مدمج وطريقة تحسين مدمجة للصور. إذ يُعد المكوَّن next/image امتدادًا لعنصر الصورة <img> في HTML، وقد طوّر ليلائم مواقع الويب الحديثة.

يتيح لك التحسين التقائي للصور إعادة تحجيم الصورة وتحسينها وتقديمها بامتدادات حديثة مثل WebP عندما يدعمها المتصفح. يقلل ذلك من الدفع بصورة كبيرة إلى أجهزة لها نافذة عرض صغيرة، كما يسمح للغة Next.js بالتبني التلقائي لتنسيقات الصور المستقبلية، وتقديمها للمتصفح الذي يدعمها.

تعمل Next.js على تحسين الصورة عند الطلب بدلًا من تحسينها أثناء بناء التطبيق. وعلى خلاف مولِّدات المواقع الساكنة والحلول الساكنة فقط، لن يزيد ذلك زمن بناء التطبيق سواءً حمّلت 10 صور أو 10 ملايين صورة.

import Image from 'next/image'

export default function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src="/me.png"
        alt="Picture of the author"
        width={500}
        height={500}
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}

متغيرات البيئة

تدعم متغيرات البيئة env. كما يفعل Create React App، ويكمن الفرق الأساسي بينهما هو البادئة التي تكشف متغير البيئة لجانب العميل.

  • حوّل بادئات متغيرات البيئة من _REACT_APP إلى _NEXT_PUBLIC.
  • تتاح متغيرات البيئة للاستخدام أثناء بناء التطبيق وعند طلب وجهات API.

تحسين نتائج البحث في محركات البحث

تستخدم معظم أمثلة Create React App العنصر react-helmet للمساعدة في إضافة بيانات وصفية meta لأغراض تحسين نتيجة ظهور الموقع في محركات البحث SEO. تستخدم Next.js في المقابل المكوّن next/head لإضافة هذه البيانات إلى العنصر </ head>. إليك مثالًا عن مكوّن SEO في تطبيق Create React App:

// src/components/seo.js

import { Helmet } from 'react-helmet'

export default function SEO({ description, title, siteTitle }) {
  return (
    <Helmet
      title={title}
      titleTemplate={siteTitle ? `%s | ${siteTitle}` : null}
      meta={[
        {
          name: `description`,
          content: description,
        },
        {
          property: `og:title`,
          content: title,
        },
        {
          property: `og:description`,
          content: description,
        },
        {
          property: `og:type`,
          content: `website`,
        },
        {
          name: `twitter:card`,
          content: `summary`,
        },
        {
          name: `twitter:creator`,
          content: twitter,
        },
        {
          name: `twitter:title`,
          content: title,
        },
        {
          name: `twitter:description`,
          content: description,
        },
      ]}
    />
  )
}

وهذا هو المثال ذاته باستخدام Next.js:

// src/components/seo.js

import Head from 'next/head'

export default function SEO({ description, title, siteTitle }) {
  return (
    <Head>
      <title>{`${title} | ${siteTitle}`}</title>
      <meta name="description" content={description} />
      <meta property="og:type" content="website" />
      <meta property="og:title" content={title} />
      <meta property="og:description" content={description} />
      <meta property="og:site_name" content={siteTitle} />
      <meta property="twitter:card" content="summary" />
      <meta property="twitter:creator" content={config.social.twitter} />
      <meta property="twitter:title" content={title} />
      <meta property="twitter:description" content={description} />
    </Head>
  )
}

تطبيقات الصفحة الواحدة

إن أردت نقل تطبيق Create React App إلى Next.js والإبقاء على تطبيق الصفحة الواحدة، انقل جميع نقاط الدخول إلى التطبيق إلى مسار التقاط اختياري لأي وجهة يُدعى pages/[[...app]].js.

// pages/[[...app]].js

import { useState, useEffect } from 'react'
import CreateReactAppEntryPoint from '../components/app'

function App() {
  const [isMounted, setIsMounted] = useState(false)

  useEffect(() => {
    setIsMounted(true)
  }, [])

  if (!isMounted) {
    return null
  }

  return <CreateReactAppEntryPoint />
}

export default App

التطبيقات المدارة ذاتيًا

إن كنت تمتلك تطبيق Create React App مُدار ذاتيًا (أو مفصول ejected باستعمال الأمر npm run eject وتديره أنت ذاتيًا بكامل ضبطه وخياراته)، إليك بعض النقاط التي ينبغي أخذها بعين الاعتبار:

  • إن كان لديك ملف مخصص مهيأ ليضم محمِّلات CSS أو Sass أو غيرها من الموجودات فهذه المحملات مدمجة في Next.js.
  • إن أضفت بنفسك ميزات JavaScript جديدة (كالسَلسَلة الاختيارية) أو شيفرات مواءمة Polyfills، فتحقق مما هو مدمج بالفعل في Next.js.
  • إن كان لديك إعدادات مخصصة لفصل الشيفرات Next.js، يمكنك إزالتها لأن Next.js تمتلك آلية فصل شيفرات تلقائية مبنية على أساس الصفحات.
  • يمكنك تخصيص إعدادات PostCSS في Next.js دون الحاجة إلى فصل التطبيق عن منصة العمل.
  • عليك العودة إلى الإعدادات الافتراضية لمفسّر Babel ومحزّم Webpack في Next.js لتقف على ما هو موجود افتراضيًا.

الانتقال من React Router

يساعدك هذا الدليل في فهم آلية الانتقال من استخدام المكتبة React Router في تحديد الوجهات إلى الاعتماد على منظومة الملفات. تستطيع أن تستخدم في Next.js المكونين next/link و next/router لكي :

  • تقلل حجم تجميعة الشيفرة بإزالة الاعتمادية React Router.
  • تحديد الوجهات في تطبيقك من خلال منظومة الملفات.
  • الاستفادة من آخر التحسينات في إطار عمل Next.js.

الأساسيات

ألغ تثبيت React Router أولًا إذ سننتقل إلى استخدام طريقة التوجيه المدمجة مع Next.js:

npm uninstall react-router-dom

يختلف المكوّن Link الذي ينفّذ عمليات التنقل في جانب العميل قليلًا عن React Router:

// قبل (React Router)
import { Link } from 'react-router-dom'

export default function App() {
  return <Link to="/about">About</Link>
}

// يعد (Next.js)
import Link from 'next/link'

export default function App() {
  return (
    <Link href="/about">
      <a>About</a>
    </Link>
  )
}

تمتلك معظم تطبيقات React التي تستخدم React Router ملفًا عال المستوى يحتوي على قائمة بكل الوجهات. إليك مثالًا:

import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'

export default function App() {
  return (
    <Router>
      <Switch>
        <Route path="/about">
          <h1>About</h1>
        </Route>
        <Route path="/blog">
          <h1>Blog</h1>
        </Route>
        <Route path="/">
          <h1>Home</h1>
        </Route>
      </Switch>
    </Router>
  )
}

يمكنك التعبير عن نفس هيكيلية التطبيق في Next.js باستخدام منظومة الملفات. فعندما يُضاف ملف إلى المجلد pagesسيكون متاحًا كوجهة:

  • pages/about.js/about
  • pages/blog.js/blog
  • pages/index.js/

الوجهات المتداخلة

تُصيّر الوجهات مثل blog/my-post/ في الشيفرة التالية إلى مكوِّن Post. فإن لم تكن هناك كتلة ديناميكية slug تحدد هوية المنشور، سيصيّر قائمة المنشورات بأكملها:

import {
  BrowserRouter as Router,
  Switch,
  Route,
  useRouteMatch,
  useParams,
} from 'react-router-dom'

export default function Blog() {
  // Nested route under /blog
  const match = useRouteMatch()

  return (
    <Router>
      <Switch>
        <Route path={`${match.path}/:slug`}>
          <Post />
        </Route>
        <Route path={match.path}>
          <h1>All Blog Posts</h1>
        </Route>
      </Switch>
    </Router>
  )
}

function Post() {
  const { slug } = useParams()
  return <h1>Post Slug: {slug}</h1>
}

تستخدم Next.js الصيغة [slug:] ضمن اسم الملف للتوجه الديناميكي بدلًا من استخدام slug: ضمن المكوّن Route. وبالإمكان الانتقال إلى Next.js بإنشاء ملفين جديدين الأول pages/blog/[slug].js (ليعرض كل الصفحات) والآخر pages/blog/[slug].js (لعرض منشورات مفردة):

// pages/blog/index.js

export default function Blog() {
  return <h1>All Blog Posts</h1>
}

// pages/blog/[slug].js

import { useRouter } from 'next/router'

export default function Post() {
  const router = useRouter()
  const { slug } = router.query

  return <h1>Post Slug: {slug}</h1>
}

التصيير من جانب الخادم

تقدم Next.js دعمًا مدمجًا للتصيير من جانب الخادم. أي بالإمكان إزالة أي نسخ عن StaticRouter في الشيفرة.

فصل الشيفرة

تقدم Next.js دعمًا مدمجًا لفصل الشيفرات، أي بالإمكان إزالة أية نسخ عن:

  • loadable/server@ و loadable/babel-plugin@ و loadable/webpack-plugin@
  • أية تعديلات على الملف babelrc. لأجل loadable/babel-plugin@

ستُفصل شيفرة كل ملف موجود في المجلد pages إلى تجميعة JavaScript خاصة خلال عملية البناء. كما تدعم Next.js الإدراج الديناميكي ()import وفق مواصفات JavaScript إصدار ES2020. وهكذا يمكنك إدراج وحدات JavaScript ديناميكيًا والعمل عليها. كما تعمل أيضًا مع التصيير من جانب الخادم.

راجع صفحة الإدراج الديناميكي لمعلومات أوفى.

استعادة موضع التمرير

تقدم Next.js دعمًا مدمجًا لاستعادة موضع التمرير scroll restoration، وبالتالي يمكنك إزالة أية مكوّنات ScrollToTop خاصة قد عرّفتها.

إن السلوك الافتراضي للمكونين next/link و next/router هو تمرير المحتوى حتى أعلى الصفحة، لكن بإمكانك أيضًا تعطيل هذا السلوك إن أردت.

أمثلة

اقرأ أيضًا

المصادر