بارگیری تنبل Lazy load
بارگذاری تنبل (Lazy Loading (opens in a new tab)) در Next.js به بهبود عملکرد بارگذاری اولیه برنامه با کاهش مقدار جاوا اسکریپت مورد نیاز برای رندر یک مسیر کمک میکند.
این قابلیت به شما امکان میدهد بارگذاری کلاینت کامپوننت ها و کتابخانههای وارد شده را به تعویق بیندازید و فقط در صورت نیاز آنها را در باندل نرمافزاری سمت کلاینت (client bundle) قرار دهید. برای مثال، ممکن است بخواهید بارگذاری یک مودال را تا زمانی که کاربر روی باز کردن آن کلیک نکند، به تعویق بیندازید.
دو روش برای پیادهسازی بارگذاری تنبل در Next.js وجود دارد:
- استفاده از Dynamic Imports با
next/dynamic - استفاده از
React.lazy()(opens in a new tab) با Suspense (opens in a new tab)
به طور پیش فرض، کامپوننتهای سمت سرور (Server Components) به طور خودکار تقسیم کد (code split (opens in a new tab)) میشوند و میتوانید از استریمینگ (streaming) برای ارسال تدریجی قطعات رابط کاربری از سرور به کاربر استفاده کنید. بارگذاری تنبل برای کامپوننتهای سمت کلاینت اعمال میشود.
next/dynamic
next/dynamic ترکیبی از React.lazy() (opens in a new tab) و Suspense (opens in a new tab) است. این قابلیت در دایرکتوریهای app و pages به صورت یکسان عمل میکند تا امکان مهاجرت افزایشی را فراهم آورد.
مثال ها
ایمپورت کردن کامپوننتهای سمت کاربر
'use client'
import { useState } from 'react'
import dynamic from 'next/dynamic'
// Client Components:
const ComponentA = dynamic(() => import('../components/A'))
const ComponentB = dynamic(() => import('../components/B'))
const ComponentC = dynamic(() => import('../components/C'), { ssr: false })
export default function ClientComponentExample() {
const [showMore, setShowMore] = useState(false)
return (
<div>
{/* Load immediately, but in a separate client bundle */}
<ComponentA />
{/* Load on demand, only when/if the condition is met */}
{showMore && <ComponentB />}
<button onClick={() => setShowMore(!showMore)}>Toggle</button>
{/* Load only on the client side */}
<ComponentC />
</div>
)
}رد شدن از SSR
هنگام استفاده از React.lazy() و Suspense، کامپوننتهای سمت کاربر به طور پیش فرض پیش-رندر pre-rendered (SSR) خواهند شد.
اگر میخواهید پیش-رندر را برای یک کامپوننت سمت کاربر غیرفعال کنید، میتوانید از گزینه ssr با مقدار false استفاده کنید:
const ComponentC = dynamic(() => import('../components/C'), { ssr: false })ایمپورت کردن کامپوننتهای سمت سرور
اگر یک کامپوننت سمت سرور را به صورت پویا ایمپورت کنید، تنها کامپوننتهای سمت کاربر که فرزند کامپوننت سمت سرور هستند به صورت تنبل بارگذاری میشوند - نه خود کامپوننت سمت سرور.
import dynamic from 'next/dynamic'
// Server Component:
const ServerComponent = dynamic(() => import('../components/ServerComponent'))
export default function ServerComponentExample() {
return (
<div>
<ServerComponent />
</div>
)
}بارگیری کتابخانههای خارجی
کتابخانههای خارجی را میتوان با استفاده از تابع import() (opens in a new tab) به صورت درخواستی بارگذاری کرد. این مثال از کتابخانه خارجی fuse.js برای جستجوی fuzzy استفاده میکند. این ماژول تنها پس از تایپ کاربر در ورودی جستجو در سمت کاربر بارگذاری میشود.
'use client'
import { useState } from 'react'
const names = ['Tim', 'Joe', 'Bel', 'Lee']
export default function Page() {
const [results, setResults] = useState()
return (
<div>
<input
type="text"
placeholder="Search"
onChange={async (e) => {
const { value } = e.currentTarget
// Dynamically load fuse.js
const Fuse = (await import('fuse.js')).default
const fuse = new Fuse(names)
setResults(fuse.search(value))
}}
/>
<pre>Results: {JSON.stringify(results, null, 2)}</pre>
</div>
)
}اضافه کردن یک کامپوننت بارگیری سفارشی loading component
import dynamic from 'next/dynamic'
const WithCustomLoading = dynamic(
() => import('../components/WithCustomLoading'),
{
loading: () => <p>Loading...</p>,
}
)
export default function Page() {
return (
<div>
{/* The loading component will be rendered while <WithCustomLoading/> is loading */}
<WithCustomLoading />
</div>
)
}ایمپورت خروجیهای نامگذاری شده Importing Named Exports
برای ایمپورت پویای یک خروجی نامگذاری شده named export، میتوانید آن را از Promise برگشتی توسط تابع import() (opens in a new tab) برگردانید:
'use client'
export function Hello() {
return <p>Hello!</p>
}import dynamic from 'next/dynamic'
const ClientComponent = dynamic(() =>
import('../components/hello').then((mod) => mod.Hello)
)