Mundarija (28)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Nega modullar?
- 2.2. Ikki tizim: ESM va CommonJS
- 2.3. ESM — export (chiqarish)
- 2.4. ESM — import (olish)
- 2.5. CommonJS — require/module.exports
- 2.6. Modul xususiyatlari
- 2.7. Dynamic import — shartli/kechiktirilgan yuklash
- 2.8. Brauzerda ESM
- 2.9. Senior Architect: Dual Package Hazard, ESM Live Bindings va Subpath Imports
- 3. Sintaksis — tez ma'lumotnoma
- 4. Batafsil kod namunalari
- Misol 1 — Named export/import (2.3, 2.4)
- Misol 2 — Default export (2.3, 2.4)
- Misol 3 — Modulni qayta ishlatish (barrel — 2.4)
- Misol 4 — Dynamic import (2.7, 2.11)
- 5. To'g'ri va noto'g'ri holatlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- 8. Eng yaxshi amaliyotlar (best practices)
- 9. Amaliy loyiha: "Modulli Utility Kutubxonasi"
- Maqsad
- Talablar (requirements)
- Maslahatlar (hint)
- "Tayyor" mezonlari (acceptance criteria)
- 10. Xulosa va keyingi bobga ko'prik
- Foydalanilgan rasmiy/ishonchli manbalar
JavaScript modullar — ES Modules (import/export) va CommonJS (2.14-bob)
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 aniq —
importkim 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:
// 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)
// 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):
// 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:
thisundefined). - Static —
importlar fayl boshida (hoisting'ga o'xshash); shartli import uchun dynamic import 2.7-bob. - Top-level await — ESM faylda
awaitniasyncfunksiyasiz, modul yuqori darajasida ishlatsa bo'ladi 2.11-bob; CommonJS'da yo'q. Modul shuawaittugaguncha kutadi:
// 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:
// 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):
<script type="module" src="app.js"></script>
<!-- module: ESM, defer 0.5-bob, o'z scope'i, CORS qoidalari -->
type="module"— avtomatikdefer(0.5: DOM tayyor bo'lganda), o'z scope (global emas). Lekin lokaldafile://bilan CORS muammosi — dev server (Vite — 11.3) kerak.
2.9. Senior Architect: Dual Package Hazard, ESM Live Bindings va Subpath Imports
Enterprise arxitekturasida modullar shunchaki fayllarga bo'lish emas, balki xotira yaxlitligi (memory integrity) va build tizimlarining xavfsizligidir.
1. ESM Live Bindings va CommonJS Snapshot farqi
Eng chuqur farqlardan biri — o'zgaruvchilar qanday uzatilishida:
CommonJS (Qiymat nusxasi — Snapshot):
// counter-cjs.js
let count = 0;
function increment() { count++; }
module.exports = { count, increment };
// app-cjs.js
const { count, increment } = require("./counter-cjs");
console.log(count); // 0
increment();
console.log(count); // ❌ HALI HAM 0! (Chunki require qiymatning nusxasini olgan, asl o'zgaruvchi bilan aloqa uzilgan)ES Modules (Jonli bog'lanish — Live Binding):
// counter-esm.js
export let count = 0;
export function increment() { count++; }
// app-esm.js
import { count, increment } from "./counter-esm.js";
console.log(count); // 0
increment();
console.log(count); // ✅ 1! (ESM modul o'zgaruvchiga to'g'ridan-to'g'ri o'qish huquqiga ega jonli havola beradi)
// count = 5; // ❌ TypeError: Assignment to constant variable (faqat eksport qiluvchi modul o'zgartira oladi)2. The Dual Package Hazard (Ikkita paket xavfi)
Kutubxona yaratuvchilari ko'pincha o'z paketlarini ham ESM (import), ham CommonJS (require) bilan ishlashini xohlashadi.
Katta xavf (Hazard):
Agar ilovangiz (yoki siz ishlatayotgan qaramliklar zanjiridagi boshqa paketlar) bitta kutubxonani bir joyda import, boshqa joyda require orqali yuklasa:
- Node.js bu ikki faylni xotirada ikkita mutlaqo alohida modul nusxasi (instance) sifatida ro'yxatga oladi.
- Agar kutubxona ichida Singleton (masalan, Database Connection Pool, Global Kesh, yoki
Symbol.for) bo'lsa, xotirada 2 ta alohida pool yaratiladi! instanceoftekshiruvlari buziladi:obj instanceof MyClasskutilmagandafalseqaytaradi, chunkiMyClassning ikkita turli konstruktori paydo bo'ladi.
Zamonaviy yechim — package.json Conditional Exports:
{
"name": "mening-kutubxonam",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
}
}
}Va holat (state) saqlovchi modullar uchun CommonJS o'rniga bitta yagona ESM kodiga havola qiluvchi CJS wrapper yozish tavsiya etiladi.
3. Subpath Imports (#imports) — Nisbiy yo'llar botqog'idan qutulish
Katta monorepo yoki yirik loyihalarda quyidagicha yoqimsiz importlarni ko'p uchratasiz:
import { auth } from "../../../../core/auth/jwt.js"; (yo'lni hisoblash azob, fayl ko'chsa hamma import buziladi).
Node.js 14.6+ da kiritilgan Subpath Imports standarti bunga mukammal nuqta qo'ydi:
// package.json:
{
"imports": {
"#services/*": "./src/services/*.js",
"#utils/*": "./src/utils/*.js"
}
}Endi loyihaning istalgan ichki papkasida turib, mutlaqo toza va xatosiz import qilish mumkin:
import { userService } from "#services/userService.js";
import { formatDate } from "#utils/dateFormat.js";Hech qanday tashqi bundler (Babel/Webpack alias) shart emas — bu to'g'ridan-to'g'ri Node.js dvigatelida ishlaydigan mahalliy standartdir!
3. Sintaksis — tez ma'lumotnoma
// 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)
// 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)); // 5Misol 2 — Default export (2.3, 2.4)
// 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)
// 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)
// Faqat tugma bosilganda og'ir modulni yuklash (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
// ❌ 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)
// ❌ ESM'da kengaytma shart (brauzer/Node ESM)
import { x } from "./utils";
// ✅ .js bilan
import { x } from "./utils.js";3) ESM va CommonJS aralashmasi
// ❌ ESM faylda require, yoki teskari
import { x } from "./m.js";
const y = require("./n"); // chalkashlik
// ✅ bittasini tanlang (zamonaviy: ESM)4) Har fayl uchun ko'p default
// ❌ 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_modulespaketlari — 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)
- Modul tuzilmasi:
src/ichidastring-utils.js,number-utils.js,array-utils.js,validatorlar.js(RegEx — 2.13) — har biri tegishli funksiyalarni named export. - Avvalgi funksiyalarni ko'chiring: 2.6 (string), 2.7 (array), 2.13 (validatsiya) loyihalaridagi funksiyalarni tegishli modulga joylang.
- Default export: bitta asosiy class (masalan
KalkulyatoryokiMatnTahlilchi) default eksport (Misol 2). - Barrel:
src/index.js— barcha modullarni bir joydan eksport (Misol 3). - Asosiy fayl (
app.js): barrel orqali import qilib, funksiyalarni ishlating. - Dynamic import: bitta "og'ir" funksiyani (masalan hisobot generatori) faqat kerak bo'lganda
await import()bilan yuklang (Misol 4). - Ishga tushiring: Node ESM bilan (
"type": "module"— 0.7) yoki brauzer<script type="module">2.8-bob. - 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
.jskengaytma shart (6-bo'lim). - Named:
export const/export function; import{ nom }. - Barrel:
export { default as X } from "./X.js"yokiexport * 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.jsmodullarni 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 aralashtirmang.
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"
O'qiganingizni mustahkamlang
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!