التحميل الكسول (Lazy Loading)
يساعد التحميل الكسول في Next.js على تحسين أداء التحميل الأولي للتطبيق عن طريق تقليل كمية JavaScript المطلوبة لعرض مسار.
يسمح لك بتأجيل تحميل مكونات العميل (Client Components) والمكتبات المستوردة، وإدراجها فقط في حزمة العميل عند الحاجة إليها. على سبيل المثال، قد ترغب في تأجيل تحميل نافذة مشروطة حتى ينقر المستخدم لفتحها.
هناك طريقتان لتنفيذ التحميل الكسول في Next.js:
- استخدام الاستيراد الديناميكي مع
next/dynamic
- استخدام
React.lazy()
مع Suspense
بشكل افتراضي، يتم تقسيم الكود (Code Splitting) تلقائيًا لمكونات الخادم (Server Components)، ويمكنك استخدام البث (Streaming) لإرسال أجزاء واجهة المستخدم تدريجيًا من الخادم إلى العميل. ينطبق التحميل الكسول على مكونات العميل.
next/dynamic
next/dynamic
هو مزيج من React.lazy()
و Suspense. يعمل بنفس الطريقة في كل من دليل app
و pages
للسماح بالهجرة التدريجية.
أمثلة
باستخدام next/dynamic
، لن يتم تضمين مكون الرأس في حزمة JavaScript الأولية للصفحة. ستقوم الصفحة بعرض fallback
الخاص بـ Suspense أولاً، متبوعًا بمكون Header
عند حل حدود Suspense
.
import dynamic from 'next/dynamic'
const DynamicHeader = dynamic(() => import('../components/header'), {
loading: () => <p>جاري التحميل...</p>,
})
export default function Home() {
return <DynamicHeader />
}
معلومة مفيدة: في
import('مسار/إلى/المكون')
، يجب كتابة المسار بشكل صريح. لا يمكن أن يكون سلسلة قوالب ولا متغيرًا. بالإضافة إلى ذلك، يجب أن تكونimport()
داخل استدعاءdynamic()
لكي يتمكن Next.js من مطابقة حزم webpack / معرفات الوحدات مع استدعاءdynamic()
المحدد وتحميلها مسبقًا قبل العرض. لا يمكن استخدامdynamic()
داخل عرض React لأنه يجب وسمها في المستوى العلوي للوحدة لكي يعمل التحميل المسبق، مشابهًا لـReact.lazy
.
مع التصديرات المسماة
لاستيراد تصدير مسماة بشكل ديناميكي، يمكنك إعادته من Promise الذي تُعيده import()
:
export function Hello() {
return <p>مرحبًا!</p>
}
// pages/index.js
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() =>
import('../components/hello').then((mod) => mod.Hello)
)
بدون عرض من جانب الخادم (SSR)
لتحميل مكون ديناميكيًا على جانب العميل فقط، يمكنك استخدام خيار ssr
لتعطيل العرض من جانب الخادم. هذا مفيد إذا كانت تبعية خارجية أو مكون تعتمد على واجهات برمجة المتصفح مثل window
.
import dynamic from 'next/dynamic'
const DynamicHeader = dynamic(() => import('../components/header'), {
ssr: false,
})
مع المكتبات الخارجية
هذا المثال يستخدم المكتبة الخارجية fuse.js
للبحث الضبابي. يتم تحميل الوحدة فقط في المتصفح بعد إدخال المستخدم في حقل البحث.
import { useState } from 'react'
const names = ['Tim', 'Joe', 'Bel', 'Lee']
export default function Page() {
const [results, setResults] = useState()
return (
<div>
<input
type="text"
placeholder="بحث"
onChange={async (e) => {
const { value } = e.currentTarget
// تحميل fuse.js ديناميكيًا
const Fuse = (await import('fuse.js')).default
const fuse = new Fuse(names)
setResults(fuse.search(value))
}}
/>
<pre>النتائج: {JSON.stringify(results, null, 2)}</pre>
</div>
)
}