تقسیم کد با واردات پویا در Next.js

چگونه با تقسیم کد و استراتژی‌های بارگذاری هوشمند، سرعت برنامه Next.js خود را افزایش دهید.

میلیکا میهایلیا
Milica Mihajlija

منتشر شده: ۸ نوامبر ۲۰۱۹

در مورد انواع مختلف تقسیم کد و نحوه استفاده از واردات پویا برای سرعت بخشیدن به برنامه‌های Next.js خود بیاموزید.

تقسیم کد مبتنی بر مسیر و مبتنی بر کامپوننت

به طور پیش‌فرض، Next.js کد جاوا اسکریپت شما را برای هر مسیر به بخش‌های جداگانه تقسیم می‌کند. وقتی کاربران برنامه شما را بارگذاری می‌کنند، Next.js فقط کد مورد نیاز برای مسیر اولیه را ارسال می‌کند. وقتی کاربران در برنامه پیمایش می‌کنند، بخش‌های مرتبط با سایر مسیرها را دریافت می‌کنند. تقسیم کد مبتنی بر مسیر، میزان اسکریپتی را که باید همزمان تجزیه و کامپایل شود، به حداقل می‌رساند و در نتیجه زمان بارگذاری صفحه سریع‌تر می‌شود.

اگرچه تقسیم کد مبتنی بر مسیر پیش‌فرض خوبی است، می‌توانید فرآیند بارگذاری را با تقسیم کد در سطح کامپوننت، بهینه‌تر کنید. اگر کامپوننت‌های بزرگی در برنامه خود دارید، ایده خوبی است که آنها را به تکه‌های جداگانه تقسیم کنید. به این ترتیب، هر کامپوننت بزرگی که حیاتی نیست یا فقط در تعاملات خاص کاربر (مانند کلیک روی یک دکمه) رندر می‌شود، می‌تواند به صورت lazy load شود.

Next.js از import() پشتیبانی می‌کند، که به شما امکان می‌دهد ماژول‌های جاوا اسکریپت (از جمله کامپوننت‌های React) را به صورت پویا وارد کنید و هر ایمپورت را به عنوان یک قطعه جداگانه بارگذاری کنید. این به شما امکان تقسیم کد در سطح کامپوننت را می‌دهد و شما را قادر می‌سازد تا بارگذاری منابع را کنترل کنید تا کاربران فقط کدی را که برای بخشی از سایت که مشاهده می‌کنند نیاز دارند، دانلود کنند. در Next.js، این کامپوننت‌ها به طور پیش‌فرض سمت سرور (SSR) رندر می‌شوند .

واردات پویا در عمل

این پست شامل چندین نسخه از یک برنامه نمونه است که از یک صفحه ساده با یک دکمه تشکیل شده است. وقتی روی دکمه کلیک می‌کنید، یک توله سگ ناز می‌بینید. با پیشرفت در هر نسخه از برنامه، خواهید دید که واردات پویا چقدر با واردات استاتیک متفاوت است و چگونه می‌توان با آنها کار کرد.

در نسخه اول برنامه، کامپوننت Puppy در components/Puppy.js قرار دارد. برای نمایش آن در صفحه، برنامه کامپوننت Puppy را با استفاده از یک دستور import استاتیک در index.js وارد می‌کند:

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

برای دیدن اینکه Next.js چگونه برنامه را بسته‌بندی می‌کند، ردیابی شبکه را در DevTools بررسی کنید:

  1. برای پیش‌نمایش سایت، روی «مشاهده برنامه» کلیک کنید. سپس روی «تمام‌صفحه» کلیک کنید. تمام صفحه .

  2. برای باز کردن DevTools، کلیدهای «Control+Shift+J» (یا «Command+Option+J» در مک) را فشار دهید.

  3. روی برگه شبکه کلیک کنید.

  4. کادر غیرفعال کردن حافظه پنهان را علامت بزنید.

  5. صفحه را دوباره بارگذاری کنید.

وقتی صفحه را بارگذاری می‌کنید، تمام کدهای لازم، از جمله کامپوننت Puppy.js ، در index.js قرار می‌گیرند:

تب DevTools Network شش فایل جاوا اسکریپت را نشان می‌دهد: index.js، app.js، webpack.js، main.js، 0.js و فایل dll (کتابخانه پیوند پویا).

وقتی دکمه‌ی «کلیک کن» را فشار می‌دهید، فقط درخواست مربوط به عکس توله سگ JPEG به تب شبکه اضافه می‌شود:

تب DevTools Network بعد از کلیک روی دکمه، همان شش فایل جاوا اسکریپت و یک تصویر را نشان می‌دهد.

نکته منفی این رویکرد این است که حتی اگر کاربران برای دیدن توله سگ روی دکمه کلیک نکنند، باید کامپوننت 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 را شامل نمی‌شود:

شبکه DevTools همان شش فایل جاوا اسکریپت را نشان می‌دهد، با این تفاوت که index.js اکنون 0.5 کیلوبایت کوچکتر شده است.

کامپوننت Puppy اکنون در یک بخش جداگانه به 1.js قرار دارد که فقط زمانی که دکمه را فشار می‌دهید بارگذاری می‌شود:

تب DevTools Network پس از کلیک روی دکمه، فایل 1.js اضافی و تصویر اضافه شده به پایین لیست فایل‌ها را نشان می‌دهد.

در برنامه‌های دنیای واقعی، کامپوننت‌ها اغلب بسیار بزرگتر هستند و بارگذاری تنبل آنها می‌تواند حجم اولیه جاوا اسکریپت شما را صدها کیلوبایت کاهش دهد.

واردات پویا با نشانگر بارگذاری سفارشی

وقتی منابع را به صورت lazy load بارگذاری می‌کنید، بهتر است یک نشانگر بارگذاری ارائه دهید تا در صورت وجود هرگونه تأخیر، بتوانید از آن استفاده کنید. در Next.js، می‌توانید این کار را با ارائه یک آرگومان اضافی به تابع dynamic() انجام دهید:

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

برای مشاهده‌ی عملکرد شاخص بارگذاری، اتصال شبکه‌ی کند را در DevTools شبیه‌سازی کنید:

  1. برای پیش‌نمایش سایت، روی «مشاهده برنامه» کلیک کنید. سپس روی «تمام‌صفحه» کلیک کنید. تمام صفحه .

  2. برای باز کردن DevTools، کلیدهای «Control+Shift+J» (یا «Command+Option+J» در مک) را فشار دهید.

  3. روی برگه شبکه کلیک کنید.

  4. کادر غیرفعال کردن حافظه پنهان را علامت بزنید.

  5. در لیست کشویی Throttling ، گزینه Fast 3G را انتخاب کنید.

  6. دکمه «کلیک کن» را فشار دهید.

حالا وقتی روی دکمه کلیک می‌کنید، مدتی طول می‌کشد تا کامپوننت بارگذاری شود و برنامه در این فاصله پیام "در حال بارگذاری..." را نمایش می‌دهد.

یک صفحه تاریک با متن

واردات پویا بدون SSR

اگر نیاز دارید که یک کامپوننت را فقط در سمت کلاینت رندر کنید (مثلاً یک ویجت چت)، می‌توانید این کار را با تنظیم گزینه ssr به false انجام دهید:

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

نتیجه‌گیری

با پشتیبانی از ایمپورت‌های پویا، Next.js امکان تقسیم کد در سطح کامپوننت را به شما می‌دهد که می‌تواند حجم فایل‌های جاوا اسکریپت شما را به حداقل برساند و زمان بارگذاری برنامه را بهبود بخشد. همه کامپوننت‌ها به طور پیش‌فرض سمت سرور رندر می‌شوند و می‌توانید هر زمان که لازم بود این گزینه را غیرفعال کنید.