Modullar

Dinamik importlar

Oldingi darslarda ko'rgan import/export โ€” bu statik importlar. Ular kuchli, lekin bir necha cheklovlari bor. Ushbu darsda dinamik import โ€” import() ifodasini o'rganamiz, u shu cheklovlardan xoli.

Statik importlarning cheklovlari

Hozirgacha ko'rgan sintaksisga statik import deyiladi. Uning quyidagi cheklovlari bor:

Birinchidan, modul yo'li dinamik bo'la olmaydi. from dan keyin faqat oddiy string turishi kerak โ€” o'zgaruvchi yoki funksiya chaqiruvi emas:

import ... from getModuleName(); // Xatolik! Faqat "string" bo'lishi kerak

Ikkinchidan, modulni shart asosida yoki ish vaqtida (runtime) yuklab bo'lmaydi:

if (condition) {
  import ...; // Xatolik! Ruxsat yo'q
}

{
  import ...; // Xatolik! Import blok ichida bo'lmasligi kerak
}

Buning sababi shundaki, import/export kodning tuzilishini (arxitekturasini) belgilashga mo'ljallangan. Bu juda yaxshi tomon โ€” kod tuzilmasini tahlil qilish, modullarni yig'ish (bundling), ishlatilmaganlarini olib tashlash (tree-shaking) mumkin bo'ladi. Lekin ba'zan bizga moslashuvchanlik kerak bo'ladi.

import() ifodasi

import(module) ifodasi modulni yuklab, uning barcha eksportlarini o'z ichiga olgan modul obyektiga hal bo'ladigan (resolve) promise qaytaradi. Uni kodning istalgan joyida chaqirish mumkin:

let modulePath = prompt('Qaysi modulni yuklaymiz?');

import(modulePath)
  .then(obj => {
    // <obj> โ€” modul obyekti, uning barcha eksportlari
  })
  .catch(err => {
    // yuklashda xatolik bo'lsa, masalan modul topilmasa
  });

import() promise qaytargani uchun uni await bilan ham ishlatish mumkin (async funksiya ichida yoki modulning yuqori darajasida):

let module = await import(modulePath);
import(...) funksiyaga o'xshab ko'rinsa-da, u oddiy funksiya emas โ€” bu maxsus sintaksis (huddi super() kabi). Shuning uchun uni o'zgaruvchiga nusxalab bo'lmaydi (let x = import ishlamaydi) yoki call/apply bilan chaqirib bo'lmaydi.

Amaliy misol: nomli eksportlarni olish

Faraz qilaylik, quyidagi eksportlarga ega modul bor:

// ๐Ÿ“ say.js
export function hi() {
  alert('Salom!');
}

export function bye() {
  alert('Xayr!');
}

Dinamik import quyidagicha bo'ladi:

let { hi, bye } = await import('./say.js');

hi();  // Salom!
bye(); // Xayr!

Yoki modul obyektini butunlayicha olib:

let say = await import('./say.js');

say.hi();  // Salom!
say.bye(); // Xayr!

Default eksportni dinamik import qilish

Modulda default eksport bo'lsa, u qaytarilgan obyektning default xossasi orqali olinadi:

// ๐Ÿ“ say.js
export default function() {
  alert('Default eksportdan salom!');
}
// olish:
let obj = await import('./say.js');
let say = obj.default;
// yoki bir qatorda:
let { default: say } = await import('./say.js');

say(); // Default eksportdan salom!

Shartli va kechiktirilgan yuklash

Dinamik importning eng katta afzalligi โ€” modulni faqat kerak bo'lganda yuklash imkoni. Bu boshlang'ich yuklash hajmini kamaytiradi va sahifani tezroq ochiladi.

Masalan, foydalanuvchi tugmani bosgandagina og'ir modulni yuklaymiz:

button.addEventListener('click', async () => {
  // modul faqat bosilganda yuklanadi
  let { renderChart } = await import('./chart.js');
  renderChart(data);
});

Yoki shart asosida turli modullarni yuklash:

async function loadLocale(lang) {
  let messages;
  if (lang === 'uz') {
    messages = await import('./locales/uz.js');
  } else {
    messages = await import('./locales/en.js');
  }
  return messages.default;
}
Bu naqsh ("lazy loading" โ€” kechiktirilgan yuklash) katta veb-ilovalarda juda foydali. Foydalanuvchi ko'rmaydigan sahifa qismlari (masalan, admin panel yoki kamdan-kam ochiladigan modal oyna) kodi faqat kerak bo'lganda yuklanadi โ€” bu boshlang'ich sahifa yuklanishini sezilarli tezlashtiradi.

Dinamik import qaerda ishlaydi?

Muhim jihat: import() ifodasi oddiy skriptlarda ham ishlaydi โ€” undan foydalanish uchun type="module" shart emas:

<!-- type="module" bo'lmasa ham import() ishlaydi -->
<script>
  import('./say.js').then(module => module.hi());
</script>
Bu statik importdan yana bir farq: statik import faqat modul ichida (type="module") ishlaydi, dinamik import() esa har qanday joyda ishlaydi.

Statik va dinamik import: solishtirma

Dinamik importni oddiy import o'rniga hamma joyda ishlatishga shoshilmang. Statik importlar kod tuzilmasini ravshan qiladi va vositalar tomonidan yaxshiroq optimallashtiriladi. Dinamik importni faqat unga haqiqiy ehtiyoj bo'lganda โ€” dinamik yo'l yoki kechiktirilgan/shartli yuklash kerak bo'lganda ishlating.

Xulosa