كيف تحايل جاتسبي على Next.js

يعمل كاتب المقال ، الذي ننشر ترجمته اليوم ، كمبرمج في Antler. هذه الشركة هي مولد بدء تشغيل عالمي. هناك أيام تجريبية في Antler عدة مرات في السنة ، تجمع بين العديد من المبدعين والمستثمرين من جميع أنحاء العالم. أجبر الوضع حول COVID-19 Antler على ترجمة أحداثه إلى تنسيق عبر الإنترنت.



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


تقديم الخادم أو مولد موقع ثابت؟


في البداية ، سأقدم لك القليل في الدورة. تعتمد جميع مشاريعنا على React ومكتبة Material-UI. ونتيجة لذلك ، قررنا في البداية عدم الابتعاد عن مجموعة التكنولوجيا هذه ، مما سيسمح لنا بضمان سرعة تطوير عالية وجعل المشروع الجديد متوافقًا مع ما لدينا بالفعل. كان الاختلاف الرئيسي بين هذا المشروع الجديد وتطبيقات React الأخرى هو أنه تم إنشاء قاعدة البيانات الخاصة بهم باستخدام التطبيق create-response-app ، وأنه تم تقديمها بالكامل على العميل (CSR ، تقديم جانب العميل). أدى هذا ، على وجه الخصوص ، إلى حقيقة أنه عندما تم تحميل التطبيق في البداية ، اضطر المستخدمون إلى مراقبة شاشة بيضاء فارغة أثناء تحميل كود جافا سكريبت للمشاريع ومعالجته وتنفيذه.

نحن بحاجة إلى مستوى لا مثيل له من الأداء. لذلك ، بدأنا نفكر في استخدام إما العرض من جانب الخادم (SSR ، أو العرض من جانب الخادم) أو مولد موقع ثابت (SSG ، Static Site Generator) بحيث يكون التحميل الأولي للتطبيقات في أسرع وقت ممكن.

يتم تخزين بياناتنا في Cloud Firestore ، ونصل إليها باستخدام Algolia. وهذا يسمح لنا بالتحكم ، على مستوى حقل قاعدة البيانات ، في وصول الجمهور إلى البيانات باستخدام مفاتيح API المقيدة. يؤدي ذلك أيضًا إلى تحسين أداء الاستعلام. من التجربة ، نعلم أن استعلامات Algolia أسرع من المعتاد ، وأن حجم Firestore JavaScript SDK المضغوط هو 86 كيلوبايت . في حالة Algolia ، يبلغ 7.5 كيلوبايت .

بالإضافة إلى ذلك ، أردنا جعل البيانات التي نقدمها للعملاء حديثة قدر الإمكان. سيساعدنا ذلك على تصحيح البيانات الخاطئة التي يمكن نشرها عن طريق الخطأ. في حين أن الممارسة القياسية لـ SSG تنص على تنفيذ الطلبات ذات الصلة للبيانات أثناء تجميع المشروع ، توقعنا أنه سيتم كتابة البيانات في قاعدة البيانات الخاصة بنا في كثير من الأحيان. على وجه الخصوص ، نحن نتحدث عن تسجيل البيانات التي بدأها المسؤولون باستخدام الواجهة القابلة للتنقلوبمبادرة من مؤسسي المشاريع باستخدام بوابة الويب. هذا يؤدي إلى التجمع التنافسي للمشروع. بالإضافة إلى ذلك ، نظرًا للسمات الهيكلية لقاعدة البيانات الخاصة بنا ، فقد تؤدي التغييرات الطفيفة إلى عمليات تجميع مشروع جديدة. هذا يجعل خط أنابيب CI / CD غير فعال للغاية. لذلك ، كنا بحاجة إلى طلبات استلام البيانات من المستودع ليتم تنفيذها في كل مرة يطلب فيها المستخدم صفحة لتحميلها. لسوء الحظ ، هذا يعني أن حلنا لن يكون مثالاً لمشروع SSG "النظيف".

في البداية ، تم إنشاء تطبيقنا على أساس Gatsby ، نظرًا لأننا استخدمنا بالفعل الصفحات المقصودة التي تم إنشاؤها على Gatsby ، وفي أحدها تم استخدام مكتبة Material-UI بالفعل. شكل الإصدار الأول من المشروع صفحة تعرض أثناء عرض البيانات "هيكل عظمي". في الوقت نفسه ، كان أول طلاء مضمون (FCP) في حدود ثانية واحدة.


تنزيل "الهيكل العظمي" للصفحة مع تحميل البيانات لاحقًا

اتضح أن الحل مثير للاهتمام ، ولكن كانت له عيوبه ، لأنه تم تنزيل بيانات إخراج الصفحة بمبادرة من العميل:

  • لمشاهدة محتويات الصفحة ، سيتعين على المستخدمين الانتظار حتى يتم تنزيل هذه الصفحة نفسها والبيانات المعروضة فيها ، والتي تم الحصول عليها من خلال 4 طلبات إلى Algolia.
  • JS- . , React «» . DOM.
  • . , , .

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


نتائج البحث في التطبيقات باستخدام Google PageSpeed ​​Insights . على اليسار هو Gatsby (SSG) ، على اليمين هو Next.js (SSR) ( الصورة الأصلية )

كان FCP لإصدار Next.js من المشروع أعلى بثلاث مرات تقريبًا من نسخته القائمة على Gatsby. كان لنسخة غاتسبي من المشروع مؤشر سرعة 3.3 ثانية ، في حين أن إصدار Next.js كان 6.2 ثانية. كان الوقت للبايت الأول (TTFB ، Time To First Byte) 2.56 ثانية عند استخدام Next.js ، و 10-20 مللي ثانية عند استخدام Gatsby.

وتجدر الإشارة إلى أن إصدار Next.js من الموقع تم نشره في خدمة أخرى (هنا استخدمنا خدمات ZEIT Now و Firebase Hosting - وهذا قد يؤثر أيضًا على زيادة TTFB). ولكن ، على الرغم من ذلك ، كان من الواضح أن نقل عمليات تحميل البيانات إلى الخادم جعل الموقع يبدو أبطأ ، على الرغم من حقيقة أن جميع مواد الصفحة تم تحميلها في نفس الوقت تقريبًا. والحقيقة هي أنه في إصدار Next.js من المشروع ، يرى المستخدم لبعض الوقت صفحة بيضاء فارغة.


لقطة شاشة توضح تحميل نسختين من التطبيق. لم يكتمل التنزيل في نفس الوقت. تتم مزامنة السجلات بمجرد الضغط على مفتاح Enter.

كل هذا يعطينا درسًا مهمًا من مجال تطوير الويب: تحتاج إلى إعطاء المستخدمين ملاحظات مرئية. وجدتإحدى الدراسات أن التطبيقات التي تستخدم شاشات الهيكل العظمي يبدو أنها يتم تحميلها بشكل أسرع.

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

أداء توليد الموقع الثابت: مقارنة Gatsby و Next.js


في حين أن الإطارين قيد النظر ، Gatsby و Next.js ، معروفان ، على التوالي ، لقدرتهما على إنشاء مواقع ثابتة وعرض الخادم ، تم تحسين دعم SSG في Next.js 9.3 ، مما يجعله منافسًا لـ Gatsby.

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

لقد أعدت إصدار Gatsby من المشروع إلى الحالة عندما تم تنزيل البيانات على العميل ، وجعلتها بحيث يكون لكلا الإصدارين من التطبيق نفس مجموعة الميزات. وبالتحديد ، كان علي إزالة ما هي مكونات Gatsby الإضافية المسؤولة عن: وظائف تحسين محركات البحث وتوليد الرموز المفضلة وبيان PWA. من أجل مقارنة حزم جافا سكريبت حصريًا التي تم إنشاؤها بواسطة الإطارات ، لم أقم بتضمين الصور والمحتويات الأخرى التي تم تنزيلها من مصادر خارجية في المشاريع. تم نشر كلا الإصدارين من التطبيق على منصة Firebase Hosting. كمرجع ، تم إنشاء نسختين من التطبيق بناءً على Gatsby 2.20.9 و Next.js 9.3.4.

قمت بتشغيل Lighthouse على جهاز الكمبيوتر الخاص بي 6 مرات لكل إصدار. أظهرت النتائج ميزة طفيفة لغاتسبي.


متوسط ​​القيم التي تم الحصول عليها بعد إطلاق 6 منارة لكل إطار عمل ( الصورة الأصلية )

من حيث تقييم الأداء العام ، كان إصدار Next.js متأخراً قليلاً عن إصدار Gatsby. وينطبق الشيء نفسه على FCP ومؤشر السرعة. إن تأخر الإدخال الأول المحتمل التالي لإصدار Next.js من التطبيق أعلى قليلاً من إصدار Gatsby.

لفهم ما يحدث بشكل أفضل ، انتقلت إلى علامة التبويب "الشبكة" في أدوات مطوري Chrome. كما اتضح ، في إصدار Next.js من المشروع ، فإن عدد الأجزاء التي يتم تقسيم شفرة جافا سكريبت إليها هو 3 أكثر من إصدار Gatsby (باستثناء ملفات البيان) ، لكن الشفرة المضغوطة أصغر 20 كيلوبايت. هل يمكن للطلبات الإضافية اللازمة لتنزيل هذه الملفات أن تفوق مزايا حزمة أصغر لدرجة أنها تضر بالأداء؟


في إصدار Gatsby من المشروع ، تم تنفيذ 7 طلبات لتنزيل 379 كيلوبايت من البيانات. في إصدار Next.js من المشروع - 12 طلبًا لتنزيل 359 كيلوبايت من البيانات ( الصورة الأصلية )

إذا قمت بتحليل أداء JavaScript ، فإن أدوات المطور تقول أن إصدار Next.js للمشروع يحتاج إلى 300 مللي ثانية إضافية للعرض الأول ، و أن هذا الإصدار يقضي المزيد من الوقت في مهمة "تقييم البرنامج النصي". في أدوات المطور ، تم وضع علامة على هذه المهمة على أنها "مهمة طويلة".


تحليل أداء خيارات المشروع المختلفة باستخدام علامة تبويب الأداء في أدوات مطوري Chrome ( الصورة الأصلية )

قارنت كود المشروع لمعرفة ما إذا كانت هناك أي اختلافات في تنفيذها يمكن أن تؤثر على الأداء. باستثناء إزالة التعليمات البرمجية والتصحيحات غير الضرورية المرتبطة بأنواع TypeScript المفقودة ، كان الاختلاف الوحيد هو تنفيذ التمرير السلس للصفحة عند الانتقال إلى أجزائها الفردية. تم تقديم هذه الميزة مسبقًا بواسطة ملفgatsby-browser.jsوتم نقلها إلى مكون تم استيراده ديناميكيًا . ونتيجة لذلك ، سيتم تشغيل هذا الرمز فقط في متصفح. (استخدمنا حزمة npm للتمرير السلس، وعند استيرادها ، يحتاج إلى كائنwindow.) قد تكون هذه المشكلة هي الجاني ، لكني لا أعرف كيف يتم التعامل معها في Next.js.

غاتسبي أكثر ملاءمة من وجهة نظر المطور


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

عندما كنت أقوم للتو بإنشاء أول إصدار من Gatsby للمشروع ، تمكنت من إضافة بعض ميزات PWA المفيدة إلى المشروع بسرعة. على سبيل المثال ، للإضافة إلى كل صفحة علامات التعريف الخاصة بي اللازمة لتحسين محركات البحث ، كان علي فقط قراءة الدليل . لتزويد المشروع ببيان PWA ، كنت بحاجة فقط لاستخدام البرنامج المساعد المناسب. من أجل تجهيز المشروع بأجهزة المفضلة التي تدعم جميع المنصات المتاحة (وفي هذه الحالة لا تزال هناك فوضى رهيبة ) ، لم يكن علي حتى أن أفعل أي شيء ، لأن دعم favicon هو جزء من البرنامج المساعد المسؤول عن البيان. إنه مريح للغاية!

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


توثيق Gatsby

صحيح ، لا يمكنني أن أسكت عن نقاط قوة Next.js:

  • بفضل البرنامج التعليمي والوثائق الموجزة لـ Next.js ، يبدو أنه يمكن تعلم هذا الإطار بشكل أسرع من Gatsby.
  • يعتمد نظام تحميل البيانات المستخدم في Next.js على الوظائف غير المتزامنة و Fetch API. ونتيجة لذلك ، عند تطوير Next.js ، لا يشعر المطور أنه بحاجة إلى تعلم GraphQL من أجل الاستفادة الكاملة من قدرات الإطار.
  • Next.js TypeScript, Gatsby , ( ). Next.js , , , .

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

في الواقع ، إذا تمكنت من إنشاء هذا التطبيق في شكل ثابت تمامًا ، فإن Next.js يناسبني بشكل أفضل ، حيث يمكنني استخدام Algolia JS-API القياسي ويمكنني الاحتفاظ بالرمز لتحميل البيانات في نفس الملف مثل ورمز المكون. نظرًا لأن Algolia لا تحتوي على واجهة برمجة تطبيقات GraphQL مدمجة ، ولا يوجد مكون إضافي لـ Gatsby لـ Algolia ، فإن تنفيذ هذه الآلية في Gatsby يتطلب إضافة هذا الرمز إلى ملف جديد . وهذا يتعارض مع الطريقة التوضيحية البديهية لوصف الصفحات.

حول طرق إضافية لتحسين أداء المشروع


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

  • في قائمة بريد March Algolia ، تمت التوصية بإضافة تلميح preconnectلزيادة سرعة تنفيذ الاستعلام. (صحيح ، لسوء الحظ ، تم إعطاء جزء رمز خاطئ في النشرة الإخبارية. هذا هو الرمز الصحيح.)
  • . JS- CSS-, webpack- Gatsby. Gatsby . , , Netlify Amazon S3. , Firebase Hosting, , .
  • نستخدم صور JPEG و PNG التي تم تحميلها من قبل المبدعين في التطبيق. نحن لا نقوم بضغطها وتحسينها. يعد تحسين هذا الجانب من تطبيقنا تحديًا كبيرًا وهو خارج نطاق هذا المشروع. بالإضافة إلى ذلك ، سيكون من الرائع إذا تم تحويل جميع هذه الصور إلى تنسيق WebP. ونتيجة لذلك ، سيتعين علينا تخزين الصور باستخدام تنسيق رسومي واحد فقط عالي الكفاءة. لسوء الحظ ، كما هو الحال مع العديد من ميزات PWA الأخرى ، فإن فريق تطوير Safari WebKit يسبب الإدمان بدعم WebP. الآن هو المتصفح الرئيسي الوحيد الذي لا يدعم هذا التنسيق.

ملخص


إذا قمنا بإيجاز ما كنا نتحدث عنه هنا ، فيمكننا أن نقول ما يلي:

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

القراء الأعزاء! هل تستخدم مولدات موقع ثابتة أو أنظمة عرض من جانب الخادم لتسريع مشاريعك؟


All Articles