WisarWisar
Dasturlash kitobi/2-QISM — JavaScript10 daqiqa

2.14-bob: Modullar — ES Modules (import/export), CommonJS

2-QISM — JavaScript (0 dan chuqurgacha) · 14-mavzu


1. Kirish va motivatsiya

Hozirgacha kodni bitta faylda yozdik. Lekin real loyiha yuzlab fayldan iborat: har komponent, har funksiya, har sahifa — alohida faylda. Ularni bir-biriga bog'lash kerak: bu fayldagi funksiyani u faylda ishlatish. Bu — modullar tizimi.

Modul — alohida fayl bo'lib, o'z kodini export qiladi (boshqalar ishlatishi uchun ochadi) va boshqa modullardan import qiladi (kerakli narsani oladi). Bu — kodni tartibli, qayta ishlatiladigan va boshqarib bo'ladigan qiladi (0.6: decomposition).

O'xshatish: modul — kutubxonadagi kitob. Har kitob o'z mavzusi (bitta vazifa); kerak bo'lsa "olib" (import) ishlatasiz. Hammasini bitta ulkan kitobga yozsangiz — topib bo'lmaydi. Modullar — bilimni bo'laklarga ajratish.

0.7-bobdagi package.json, node_modules (npm paketlari ham modullar!), va React/Node loyihalarining butun tuzilishi — modullarga tayanadi. import/exportsiz zamonaviy loyiha yo'q.


2. Nazariya — chuqur tushuntirish

2.1. Nega modullar?

Bitta katta fayl muammolari: nom konfliktlari (global scope — 2.4), topish qiyin, qayta ishlatib bo'lmaydi, jamoada ishlash dahshat. Modullar:

  • Inkapsulyatsiya — har modul o'z scope'i 2.4-bob; faqat export qilingani ko'rinadi.
  • Qayta ishlatish — bir modulni ko'p joyda import.
  • Tartib — har fayl bitta mas'uliyat 9.1-bob.
  • Bog'liqliklar aniqimport kim kimga bog'liqligini ko'rsatadi.

2.2. Ikki tizim: ESM va CommonJS

JS'da ikki modul tizimi bor:

ES Modules (ESM) CommonJS (CJS)
Sintaksis import/export require/module.exports
Yuklash asinxron, static sinxron
Qayerda brauzer + zamonaviy Node eski Node (default edi)
Holat zamonaviy standart eski (hali keng)

Qaysini? Yangi kodda — ESM (import/export). U brauzerda ham, Node'da ham ishlaydi (standart). CommonJS — eski Node loyihalarida uchraydi, bilish kerak. package.jsonda "type": "module" 0.7-bob — ESM'ni yoqadi.

2.3. ESM — export (chiqarish)

Ikki usul: named (nomli) va default:

js
// matematika.js — NAMED export (bir nechta)
export const PI = 3.14159;
export function qosh(a, b) { return a + b; }
export class Kalkulyator {}

// yoki oxirida birga:
const ayir = (a, b) => a - b;
export { ayir };

// DEFAULT export — faylda BITTA (asosiy narsa)
export default function asosiy() {}

2.4. ESM — import (olish)

js
// Named import — {} ichida, AYNAN o'sha nom bilan
import { PI, qosh } from "./matematika.js";

// Qayta nomlash (alias)
import { qosh as qoshish } from "./matematika.js";

// Default import — {} SIZ, istalgan nom bilan
import asosiy from "./matematika.js";

// Hammasini birga
import asosiy, { PI, qosh } from "./matematika.js";

// Barchasini obyekt sifatida (namespace)
import * as math from "./matematika.js";
math.PI;  math.qosh(2, 3);

Named vs default farqi: named{ aniqNom } (export'dagi nom bilan); default{} siz, istalgan nom. Bir faylda ko'p named, lekin faqat bitta default.

2.5. CommonJS — require/module.exports

Eski Node tizimi (bilish kerak):

js
// matematika.js — eksport
const qosh = (a, b) => a + b;
module.exports = { qosh, PI: 3.14 };   // obyekt sifatida
// yoki: exports.qosh = qosh;

// app.js — import
const { qosh } = require("./matematika");   // require — sinxron
const math = require("./matematika");        // hammasi
math.qosh(2, 3);

ESM CJS: ikkalasini aralashtirish muammoli. Bitta loyihada bittasini tanlang. Zamonaviy: ESM. Node paketida package.json "type" belgilaydi 0.7-bob.

2.6. Modul xususiyatlari

  • Har modul o'z scope'i 2.4-bob — modul ichidagi o'zgaruvchi global emas (avtomatik himoya).
  • Bir marta bajariladi — modul birinchi importda bir marta ishga tushadi, natija cache'lanadi (keyingi import'lar shu nusxani oladi).
  • Strict mode — ESM doim strict (2.5: this undefined).
  • Staticimportlar fayl boshida (hoisting'ga o'xshash); shartli import uchun dynamic import 2.7-bob.
  • Top-level await — ESM faylda awaitni async funksiyasiz, modul yuqori darajasida ishlatsa bo'ladi 2.11-bob; CommonJS'da yo'q. Modul shu await tugaguncha kutadi:
js
// data.js — ESM, top-level await (async funksiya KERAK emas)
const javob = await fetch("/sozlama.json");
export const sozlama = await javob.json();

2.7. Dynamic import — shartli/kechiktirilgan yuklash

import() funksiyasi — modulni kerak bo'lganda (asinxron) yuklaydi 2.11-bob:

js
// Faqat kerak bo'lganda yuklash (Promise qaytaradi — 2.11)
async function ogirModulIshlat() {
  const { ogirFunksiya } = await import("./ogir-modul.js");
  ogirFunksiya();
}
// Foydasi: boshlang'ich yuklanishni yengil qiladi (code splitting — 11.8)

Bu — React'da React.lazy 11.8-bob va Next.js'da (13) bundle optimizatsiyasining asosi.

2.8. Brauzerda ESM

HTMLda type="module" bilan (1.1, 0.5):

html
<script type="module" src="app.js"></script>
<!-- module: ESM, defer 0.5-bob, o'z scope'i, CORS qoidalari -->

type="module" — avtomatik defer (0.5: DOM tayyor bo'lganda), o'z scope (global emas). Lekin lokalda file:// bilan CORS muammosi — dev server (Vite — 11.3) kerak.


3. Sintaksis — tez ma'lumotnoma

js
// ESM (zamonaviy)
export const x = 1;                  // named
export default fn;                   // default
export { a, b };
import { x, a as b } from "./m.js";  // named (alias)
import fn from "./m.js";             // default
import * as m from "./m.js";         // namespace
const m = await import("./m.js");    // dynamic (2.7)

// CommonJS (eski Node)
module.exports = { x };
const { x } = require("./m");

4. Batafsil kod namunalari

Misol 1 — Named export/import (2.3, 2.4)

js
// utils/matematika.js
export const PI = 3.14159;
export function aylanaYuza(r) { return PI * r ** 2; }
export function qosh(a, b) { return a + b; }

// app.js
import { PI, aylanaYuza, qosh as qoshish } from "./utils/matematika.js";
console.log(aylanaYuza(5));   // 78.54
console.log(qoshish(2, 3));   // 5

Misol 2 — Default export (2.3, 2.4)

js
// User.js — asosiy narsa = class
export default class User {
  constructor(ism) { this.ism = ism; }
}
// qo'shimcha named ham bo'lishi mumkin
export const MAX_USERS = 100;

// app.js
import User, { MAX_USERS } from "./User.js";   // default {} siz, named {} bilan
const u = new User("Ali");

Misol 3 — Modulni qayta ishlatish (barrel — 2.4)

js
// components/index.js — "barrel" (bir joydan hammasi)
export { default as Tugma } from "./Tugma.js";
export { default as Karta } from "./Karta.js";
export { default as Modal } from "./Modal.js";

// app.js — bitta joydan import (qulay)
import { Tugma, Karta, Modal } from "./components/index.js";
// (React loyihalarida juda keng tarqalgan — 11)

Misol 4 — Dynamic import (2.7, 2.11)

js
// Faqat tugma bosilganda og'ir modulni yukla (code splitting g'oyasi)
document.querySelector("#export").addEventListener("click", async () => {
  // PDF kutubxonasi faqat KERAK bo'lganda yuklanadi (boshlang'ich yengil)
  const { pdfYarat } = await import("./pdf-generator.js");
  pdfYarat();
});

5. To'g'ri va noto'g'ri holatlar

1) Named/default'ni aralashtirish

js
//  default'ni {} bilan import
import { User } from "./User.js";   // User default eksport bo'lsa — undefined!

//  default {} siz
import User from "./User.js";

2) Fayl kengaytmasini unutish (ESM, brauzer/Node)

js
//  ESM'da kengaytma shart (brauzer/Node ESM)
import { x } from "./utils";

//  .js bilan
import { x } from "./utils.js";

3) ESM va CommonJS aralashmasi

js
//  ESM faylda require, yoki teskari
import { x } from "./m.js";
const y = require("./n");   // chalkashlik

//  bittasini tanla (zamonaviy: ESM)

4) Har fayl uchun ko'p default

js
//  bir faylda 2 ta default — xato
export default a;
export default b;

//  bitta default + named (Misol 2)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Cannot use import statement outside a module

Sababi: Node ESM'ni yoqmagan. Yechimi: package.jsonda "type": "module" 0.7-bob, yoki fayl .mjs; brauzerda <script type="module"> 2.8-bob.

Xato 2 — Cannot find module './x'

Sababi: noto'g'ri yo'l yoki kengaytma yo'q (0.2: path). Yechimi: to'g'ri relative path (./, ../ — 0.2); ESM'da .js kengaytma; harf registri (0.2: Linux!).

Xato 3 — X is not a function / undefined (import)

Sababi: named/default chalkashligi 2.4-bob. Yechimi: eksport turini tekshiring — default {} siz, named {} bilan.

Xato 4 — require is not defined (ESM'da)

Sababi: ESM faylda CommonJS require 2.5-bob. Yechimi: import ishlating; yoki fayl CommonJS bo'lsa .cjs.

Xato 5 — Circular dependency (aylanma bog'liqlik)

Sababi: A B A import (bir-birini chaqiradi). Yechimi: umumiy kodni uchinchi modulga ajrating; arxitekturani qayta ko'ring 9.3-bob.


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • npm/package.json (0.7, 5.2): node_modules paketlari — modullar; "type": "module".
  • Node/Express (5): har route/service alohida modul.
  • React (11): har komponent — modul; barrel export (Misol 3).
  • Code splitting (11.8, 13): dynamic import — React.lazy, Next bundle.
  • TypeScript (7): modul + tip; import type.
  • Build (Vite — 11.3): ESM asosida; tree-shaking (ishlatilmagan eksportni olib tashlash).
  • Funksional kod 2.15-bob: toza funksiyalarni modulga ajratish.

8. Eng yaxshi amaliyotlar (best practices)

  • Yangi kodda ESM (import/export) — zamonaviy standart 2.2-bob.
  • Bitta fayl — bitta mas'uliyat 9.1-bob; kodni mantiqli modullarga bo'ling.
  • Named export odatda afzal (aniq nom, tree-shaking); default — faylning asosiy narsasi uchun 2.4-bob.
  • Barrel (index.js) bilan importni soddalashtiring, lekin ortiqcha qilmang (Misol 3).
  • Relative path to'g'ri (./, ../), kengaytma bilan (0.2, 6-bo'lim).
  • ESM/CJS aralashtirmang — bitta tizim 2.5-bob.
  • Dynamic import bilan og'ir modulni kechiktiring (code splitting — 2.7).
  • Circular dependency'dan qoching — umumiyni ajrating (6-bo'lim).

9. Amaliy loyiha: "Modulli Utility Kutubxonasi"

Oldingi boblardagi (2.3, 2.6, 2.7) funksiyalarni modullarga tashkil qilasiz.

Maqsad

import/export (named + default), barrel va dynamic import'ni amalda qo'llab, kodni professional, modulli tuzilishda tashkil qilish.

Talablar (requirements)

  1. Modul tuzilmasi: src/ ichida string-utils.js, number-utils.js, array-utils.js, validatorlar.js (RegEx — 2.13) — har biri tegishli funksiyalarni named export.
  2. Avvalgi funksiyalarni ko'chiring: 2.6 (string), 2.7 (array), 2.13 (validatsiya) loyihalaridagi funksiyalarni tegishli modulga joylang.
  3. Default export: bitta asosiy class (masalan Kalkulyator yoki MatnTahlilchi) default eksport (Misol 2).
  4. Barrel: src/index.js — barcha modullarni bir joydan eksport (Misol 3).
  5. Asosiy fayl (app.js): barrel orqali import qilib, funksiyalarni ishlating.
  6. Dynamic import: bitta "og'ir" funksiyani (masalan hisobot generatori) faqat kerak bo'lganda await import() bilan yuklang (Misol 4).
  7. Ishga tushiring: Node ESM bilan ("type": "module" — 0.7) yoki brauzer <script type="module"> 2.8-bob.
  8. Har modul o'z scope'ida (global o'zgaruvchi yo'q — 2.6).

Maslahatlar (hint)

  • package.jsonga "type": "module" qo'shing 0.7-bob — ESM uchun.
  • ESM'da import yo'lida .js kengaytma shart (6-bo'lim).
  • Named: export const/export function; import { nom }.
  • Barrel: export { default as X } from "./X.js" yoki export * from "./m.js".
  • Dynamic: const { fn } = await import("./modul.js") (async ichida — 2.11).
  • Harf registriga e'tibor (0.2: Linux serverda muhim).

"Tayyor" mezonlari (acceptance criteria)

  • Kamida 4 modul, har biri named export bilan.
  • Bitta default export ishlatilgan.
  • Barrel (index.js) orqali import ishlaydi.
  • app.js modullarni to'g'ri import qilib ishlatadi.
  • Dynamic import (await import) bitta modulda ishlaydi.
  • ESM to'g'ri sozlangan ("type": "module" yoki brauzer module).
  • Hech qaysi modul global o'zgaruvchi yaratmaydi.

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda kodni fayllarga bo'lib bog'lashni — modullarni o'rgandik:

  • Modul — alohida fayl; o'z scope'i 2.4-bob, export (ochadi) / import (oladi); bir marta bajariladi, cache'lanadi.
  • ESM (zamonaviy): export/import (named {} bilan, default {} siz), asinxron/static; brauzer + Node.
  • CommonJS (eski Node): module.exports/require, sinxron.
  • Dynamic import (import()) — kerak bo'lganda yuklash (code splitting — 11.8).
  • Best: ESM, bitta mas'uliyat, named afzal, to'g'ri path, ESM/CJS aralashtirma.

Keyingi bob — 2.15-bob: Functional programming asoslari — immutability, pure functions, HOF. 2.3 (HOF), 2.7 (map/filter/reduce), 2.8 (immutability) da funksional g'oyalarni sezdik; endi ularni bir tizim sifatida — funksional dasturlash paradigmasi — o'rganamiz. Bu — toza, bashoratli, test qilishga oson kod yozishning kuchli usuli.


Foydalanilgan rasmiy/ishonchli manbalar

  • MDN Web Docs — JavaScript modules, import/export, dynamic import
  • Node.js docs — ECMAScript modules, CommonJS
  • MDN — ESM vs CommonJS farqlari, type="module"

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
2.14-bob: Modullar — ES Modules (import/export), CommonJS — Wisar