تقسيم الرمز باستخدام عمليات الاستيراد الديناميكية في Next.js

كيفية زيادة سرعة تطبيق Next.js باستخدام استراتيجيات تقسيم الرموز والتحميل الذكي

ميلييكا ميهاجليا
ميليكا ميهاجليا

ما الذي ستتعلمه؟

توضّح هذه المشاركة الأنواع المختلفة من تقسيم الرموز وكيفية استخدام عمليات الاستيراد الديناميكية لتسريع تطبيقات Next.js.

تقسيم الرموز المستندة إلى المسار والرموز المستندة إلى المكونات

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

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

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

عمليات الاستيراد الديناميكية قيد التنفيذ

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

في الإصدار الأول من التطبيق، يعيش الجرو في "components/Puppy.js". لعرض الجرو على الصفحة، يستورد التطبيق المكوّن Puppy في index.js باستخدام عبارة استيراد ثابتة:

import Puppy from "../components/Puppy";

لمعرفة كيفية جمع Next.js للتطبيق، افحص تتبُّع الشبكة في "أدوات مطوري البرامج":

  1. لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق، ثم اضغط على ملء الشاشة ملء الشاشة.

  2. اضغط على "Control+Shift+J" (أو "Command+Option+J" على نظام التشغيل Mac) لفتح "أدوات مطوّري البرامج".

  3. انقر على علامة التبويب الشبكة.

  4. ضع علامة في مربّع الاختيار إيقاف ذاكرة التخزين المؤقت.

  5. إعادة تحميل الصفحة

عند تحميل الصفحة، يتم تجميع كل الرموز اللازمة، بما في ذلك المكوِّن Puppy.js، في index.js:

علامة التبويب "الشبكة" ضمن أدوات مطوّري البرامج تعرض ستة ملفات JavaScript، وهي index.js وapp.js وwebpack.js وmain.js و0.js وملف dll (مكتبة الرابط الديناميكي).

عند الضغط على زر انقر هنا، تتم إضافة طلب ملف JPEG فقط إلى علامة التبويب الشبكة:

تظهر علامة التبويب "الشبكة" ضمن "أدوات مطوري البرامج" بعد النقر على الزر، وتعرض ملفات JavaScript الستة نفسها وصورة واحدة.

والجانب السلبي لهذا الأسلوب هو أنّه حتى إذا لم ينقر المستخدمون على الزر لرؤية الجرو، عليهم تحميل المكوّن Puppy لأنه مضمَّن في index.js. في هذا المثال الصغير، لا يمثل ذلك مشكلة كبيرة، ولكن في التطبيقات الواقعية، غالبًا ما يكون تحميل المكونات الكبيرة تحسينًا كبيرًا فقط عند الضرورة.

تحقق الآن من إصدار ثانٍ من التطبيق، حيث يتم استبدال الاستيراد الثابت باستيراد ديناميكي. يتضمن Next.js next/dynamic، مما يجعل من الممكن استخدام عمليات الاستيراد الديناميكية لأي مكونات في Next:

import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";

// ...

const Puppy = dynamic(import("../components/Puppy"));

اتّبِع الخطوات الواردة في المثال الأول لفحص تتبُّع الشبكة.

عند تحميل التطبيق لأول مرة، يتم تنزيل index.js فقط. وفي هذه المرة، يكون الحجم أصغر بمقدار 0.5 كيلوبايت (انخفاضًا من 37.9 كيلوبايت إلى 37.4 كيلوبايت) لأنّه لا يتضمّن الرمز الخاص بالمكوِّن Puppy:

تعرض شبكة أدوات مطوّري البرامج ملفات JavaScript الستة نفسها، باستثناء ملف index.js الذي أصبح الآن أصغر حجمًا بمقدار 0.5 كيلوبايت.

أصبح المكوِّن Puppy الآن في مقطع منفصل باسم 1.js يتم تحميله فقط عند الضغط على الزرّ:

علامة التبويب "شبكة أدوات مطوّري البرامج" بعد النقر على الزر، وتعرض ملف 1.js الإضافي والصورة التي تمت إضافتها إلى أسفل قائمة الملفات.

في التطبيقات العملية، غالبًا ما تكون المكونات أكبر بكثير، ويمكن أن يؤدي التحميل الكسول لها إلى خفض حمولة JavaScript الأولية بمقدار مئات الكيلوبايت.

عمليات الاستيراد الديناميكية مع مؤشر تحميل مخصّص

عند إجراء التحميل الكسول للموارد، من الأفضل توفير مؤشر تحميل في حال حدوث أي تأخيرات. في Next.js، يمكنك إجراء ذلك من خلال توفير وسيطة إضافية للدالة dynamic():

const Puppy = dynamic(() => import("../components/Puppy"), {
  loading: () => <p>Loading...</p>
});

لعرض مؤشر التحميل أثناء استخدامه، عليك محاكاة الاتصال البطيء بالشبكة في "أدوات مطوّري البرامج":

  1. لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق، ثم اضغط على ملء الشاشة ملء الشاشة.

  2. اضغط على "Control+Shift+J" (أو "Command+Option+J" على نظام التشغيل Mac) لفتح "أدوات مطوّري البرامج".

  3. انقر على علامة التبويب الشبكة.

  4. ضع علامة في مربّع الاختيار إيقاف ذاكرة التخزين المؤقت.

  5. في القائمة المنسدلة تقييد، اختَر شبكة الجيل الثالث السريعة.

  6. اضغط على الزر انقر هنا.

والآن عندما تنقر على الزر، يستغرق تحميل المكون بعض الوقت ويعرض التطبيق الرسالة "جارٍ التحميل..." في هذه الأثناء.

شاشة داكنة تتضمن النص

عمليات الاستيراد الديناميكية بدون SSR

إذا كنت تريد عرض مكوّن من جهة العميل فقط (مثل أداة محادثة)، يمكنك إجراء ذلك من خلال ضبط خيار ssr على false:

const Puppy = dynamic(() => import("../components/Puppy"), {
  ssr: false,
});

الخلاصة

بفضل إمكانية الاستيراد الديناميكي، يتيح لك Next.js تقسيم الرموز على مستوى المكوِّن، ما قد يؤدي إلى تقليل حمولات بيانات JavaScript وتحسين وقت تحميل التطبيق. يتم عرض جميع المكونات من جانب الخادم افتراضيًا ويمكنك إيقاف هذا الخيار عند الضرورة.