Dynamic Import — komponentlarni bo'laklash
Muammodan boshlaylik
Mahsulot sahifasi:
- Narx tarixi grafigi (
recharts— ~200 KB) — faqat "Grafik" tabi ochilganda kerak - Xarita (
leaflet— ~150 KB) — sahifaning eng pastida - Rasm tahrirlagich — faqat sotuvchi "Tahrirlash" ni bosganda
- Chat vidjeti — foydalanuvchilarning 3% i ishlatadi
Hammasi birinchi yuklanishda keladi. Foydalanuvchilarning 90% i ularni hech qachon ochmaydi, lekin hammasi kutadi.
Hayotiy o'xshatma
Sayohatga butun uyni olib ketmaysiz. Kerakli narsalar — chamadonda (asosiy bundle). Qolganlari — uyda: kerak bo'lsa, pochta orqali yuborishadi (dynamic import). Chamadon yengil, yo'lga tez chiqasiz.
next/dynamic
'use client'
import dynamic from 'next/dynamic'
import { useState } from 'react'
const NarxGrafigi = dynamic(() => import('@/components/NarxGrafigi'), {
loading: () => <div className="h-64 animate-pulse rounded-lg bg-gray-100" />,
})
export function MahsulotTablari({ mahsulotId }: { mahsulotId: string }) {
const [tab, setTab] = useState<'tavsif' | 'grafik'>('tavsif')
return (
<div>
<button onClick={() => setTab('tavsif')}>Tavsif</button>
<button onClick={() => setTab('grafik')}>Narx tarixi</button>
{tab === 'grafik' && <NarxGrafigi mahsulotId={mahsulotId} />}
</div>
)
}
NarxGrafigivarecharts— alohida JavaScript fayl (chunk)- U faqat komponent birinchi marta render qilinganda yuklanadi
loading— yuklanayotganda ko'rsatiladigan joy saqlovchi (CLS ga qarshi — aynan o'lchamda)
SSR ni o'chirish
Faqat brauzerda ishlaydigan kutubxonalar (window, document ga murojaat qiladiganlar — xaritalar, ba'zi tahrirlagichlar):
'use client'
import dynamic from 'next/dynamic'
const Xarita = dynamic(() => import('@/components/Xarita'), {
ssr: false,
loading: () => <div className="h-80 bg-gray-100" />,
})
[!WARNING]
ssr: falsefaqat Client Component ichida ishlatiladi. Server Component dadynamic(..., { ssr: false })— build xatosi. Uni alohida'use client'faylga o'rab, o'sha komponentni Server Component dan import qiling.
// components/XaritaClient.tsx
'use client'
import dynamic from 'next/dynamic'
export const XaritaClient = dynamic(() => import('./Xarita'), { ssr: false })
// app/dokonlar/page.tsx (Server Component)
import { XaritaClient } from '@/components/XaritaClient'
export default function Page() {
return <XaritaClient />
}
Nomlangan export
const Grafik = dynamic(() => import('recharts-wrapper').then((m) => m.LineGrafik))
import() modul obyektini qaytaradi — kerakli export ni .then bilan oling.
Ko'rinishga kelganda yuklash
Sahifa pastidagi og'ir komponent — foydalanuvchi u yerga scroll qilganda:
'use client'
import dynamic from 'next/dynamic'
import { useEffect, useRef, useState } from 'react'
const Xarita = dynamic(() => import('./Xarita'), { ssr: false })
export function KechXarita() {
const ref = useRef<HTMLDivElement>(null)
const [korindi, setKorindi] = useState(false)
useEffect(() => {
const kuzatuvchi = new IntersectionObserver(([e]) => {
if (e.isIntersecting) {
setKorindi(true)
kuzatuvchi.disconnect()
}
}, { rootMargin: '200px' })
if (ref.current) kuzatuvchi.observe(ref.current)
return () => kuzatuvchi.disconnect()
}, [])
return <div ref={ref} className="h-80">{korindi && <Xarita />}</div>
}
rootMargin: '200px' — ekranga yetishidan biroz oldin yuklashni boshlash.
Hodisada kutubxona yuklash
Komponent emas, oddiy kutubxona kerak bo'lsa:
'use client'
export function EksportTugmasi({ malumot }: { malumot: unknown[] }) {
async function eksport() {
const XLSX = await import('xlsx') // faqat bosilganda
const varaq = XLSX.utils.json_to_sheet(malumot)
const kitob = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(kitob, varaq, 'Hisobot')
XLSX.writeFile(kitob, 'hisobot.xlsx')
}
return <button onClick={eksport}>Excel ga yuklab olish</button>
}
Oldindan yuklash
Foydalanuvchi tugma ustiga kelganda — bosishidan oldin yuklashni boshlash:
<button onMouseEnter={() => import('xlsx')} onClick={eksport}>
Server Component lar va bo'laklash
// Server Component — dynamic kerak emas
import { OgirServerKomponent } from './OgirServerKomponent'
Server Component lar brauzerga JavaScript sifatida yuborilmaydi — ularni "bo'laklash" kerak emas. App Router sahifalar bo'yicha kodni avtomatik bo'ladi: har bir route faqat o'z kodini yuklaydi. dynamic — Client Component lar ichidagi og'ir qismlar uchun.
[!TIP] Nimani dinamik qilish kerak: birinchi ekranda ko'rinmaydigan, kam ishlatiladigan va og'ir (50 KB+) komponentlar. Kichik komponentlarni dinamik qilish — foydadan ko'ra ko'proq so'rov va kechikish.
Tez-tez uchraydigan xatolar
1. Birinchi ekrandagi asosiy kontentni dinamik qilish
Hero bo'lim dynamic — LCP yomonlashadi: avval asosiy bundle, keyin yana bitta so'rov.
2. loading siz
Komponent yuklanganda kontent "sakraydi" (CLS). Aynan o'lchamdagi joy saqlovchi.
3. Server Component da ssr: false
Build xatosi — client wrapper orqali.
Xulosa
dynamic(() => import('./X'), { loading }) — alohida chunk, kerak bo'lganda yuklanadi
ssr: false — faqat brauzer kutubxonalari; faqat Client Component ichida
Nomlangan export — .then(m => m.Nom)
IntersectionObserver — ko'rinishga kelganda yuklash
await import('lib') — hodisada kutubxona; onMouseEnter — oldindan yuklash
Server Component — bo'laklash kerak emas; route lar avtomatik bo'linadi
Faqat og'ir, kam ishlatiladigan, birinchi ekrandan tashqaridagilarni
Keyingi dars
57-dars: Image optimizatsiya — chuqurroq, sizes, priority
next/image ning nozik sozlamalari — har bir qurilmaga to'g'ri o'lchamdagi rasm.