IlmHamroh
JavaScript Full-stack/24-qism. Node.js10/55-dars15 daqiqa
Mundarija (27)

CommonJS ichidan: require qanday ishlaydi — module wrapper, resolution va circular require

Qisqacha: require("x") besh qadamdan iborat. (1) Resolution — x ni to'liq fayl yo'liga aylantirish: .js, .json, .node kengaytmalari, papkadagi index.js, package.json dagi main, yuqoriga qarab node_modules. (2) keshni tekshirish — require.cache da bo'lsa, darhol qaytarish; (3) yangi Module obyekti va uni keshga oldindan yozish; (4) faylni module wrapper — (function (exports, require, module, __filename, __dirname) { … }) ichida bajarish; (5) module.exports ni qaytarish. Uchinchi qadam tufayli sikl (circular) require xato bermaydi — u yarim tayyor eksportni beradi: kanon o'lchovida b ichida a.ready — false.

Bu darsda

  • require ning besh qadamini aytib bera olasiz va Module.wrap bilan wrapper'ni o'z ko'zingiz bilan ko'rasiz.
  • Node faylni qaysi tartibda qidirishini bilasiz: kengaytma, papka, main, node_modules zanjiri.
  • require.resolve, require.resolve.paths, module.paths, require.main bilan modul tizimini tekshira olasiz.
  • Sikl require nega "yarim tayyor" obyekt berishini tushunasiz va uni tuzatishning uch yo'lini bilasiz.
  • JSON keshi va module.exports = {...} almashtirish bilan bog'liq ikki nozik tuzoqni taniysiz.

Oldin bilishingiz kerak: CommonJS va ESM bilan o'zaro ishlash, node_modules ichida: modul qidirish, Global obyektlar: Node va brauzer farqi.

1. Nega bu kerak?

CommonJS va ESM bilan o'zaro ishlash darsida CommonJS'ni foydalanuvchi sifatida o'rgandingiz: require, module.exports, exports tuzog'i, kesh. node_modules ichida darsida paket qidirish va hoisting'ni ko'rdingiz. Bu dars — "kapotni ochish": require ichida aynan nima bo'ladi.

Nega bu kerak, agar yangi kod ESM'da yozilsa? Uchta sabab:

  1. npm'dagi paketlarning katta qismi hali ham CommonJS. Xato chiqqanda (Cannot find module, undefined is not a function) stek izida aynan shu mexanizm ko'rinadi.
  2. Sikl bog'liqlik — eng sirli xatolardan biri. Kod ba'zan ishlaydi, ba'zan yo'q, faqat require tartibiga qarab. Mexanizmni bilmasdan uni topish qiyin.
  3. ESM qoidalari (ES Modules Node'da) CommonJS bilan taqqoslaganda tushuniladi. Keyingi ikki dars shu poydevorga quriladi.

O'xshatish: kutubxona. Siz "Navoiy, Xamsa" deb so'raysiz (require). Kutubxonachi avval katalogdan javon va raqamni topadi (resolution). Kitob allaqachon qo'lingizda bo'lsa, o'shani beradi (kesh). Bo'lmasa — formulyar ochadi (yangi Module), kitobni olib keladi va o'qishga beradi (bajarish).

2. require ning besh qadami

2.1 Umumiy oqim

Node manbasida bu ish Module._load funksiyasida. Soddalashtirilgan ko'rinishi:

flowchart TD
  R["require('./kurs')"] --> S["1. resolution<br/>to'liq yo'l"]
  S --> C{"2. keshda bormi?"}
  C -->|ha| E["module.exports<br/>qaytariladi"]
  C -->|yo'q| N["3. new Module<br/>keshga yoziladi"]
  N --> W["4. wrapper ichida<br/>bajariladi"]
  W --> E

Uchinchi qadamdagi tartibga e'tibor bering: modul keshga bajarishdan oldin yoziladi. Hozircha bu mayda detal kabi ko'rinadi — sikl require bo'limida aynan u hal qiluvchi bo'ladi.

Ichki modullar (fs, node:path) uchun yo'l qisqaroq: ular fayl emas, Node ichiga qurilgan, shuning uchun 1–4 qadamlar o'rniga tayyor obyekt beriladi.

2.2 Module wrapper — haqiqiy matni

CommonJS va ESM bilan o'zaro ishlash darsida wrapper "taxminan shunday" deb ko'rsatilgan edi. Endi aynan Node'dan so'raymiz. node:module dagi wrap funksiyasi istalgan matnni xuddi require qilgandek o'raydi:

js
const { wrap } = require("node:module");
console.log(wrap("return 1"));

Konsolda:

text
(function (exports, require, module, __filename, __dirname) { return 1
});

Kanon tajribasida Module.wrapper massivi ham tekshirilgan — u aynan shu ikki bo'lakdan iborat: '(function (exports, require, module, __filename, __dirname) { ' va '\n});'. Birinchi bo'lak ochilish qavsi bilan bir qatorda tugaydi. Shuning uchun faylingizning 1-qatori o'ralgan kodda ham 1-qator bo'lib qoladi va xato izidagi qator raqamlari to'g'ri chiqadi.

Wrapper'ni ichkaridan tekshirish (kanon tajribasi, wrapper.cjs):

text
arguments.length = 5 | this === module.exports: true | __filename oxiri: wrapper.cjs

Faylning eng yuqorisida arguments bor (oddiy funksiyadagi kabi) va uning uzunligi 5. Bu — "har fayl funksiya ichida" degan gapning to'g'ridan-to'g'ri isboti.

2.3 Kengaytmaga qarab yuklovchi

To'rtinchi qadamdagi "bajarish" fayl turiga bog'liq. Node'da uchta yuklovchi bor:

js
const { _extensions } = require("node:module");
console.log(Object.keys(_extensions));

Konsolda:

text
[ '.js', '.json', '.node' ]
Kengaytma Nima qilinadi
.js (va .cjs) wrapper ichida V8 bilan bajariladi
.json JSON.parse qilinadi, natija module.exports ga
.node C++ da yozilgan "native addon" yuklanadi

_ bilan boshlangan nom — ichki API degani. Uni o'qish foydali, lekin o'zgartirish yo'q. Eski kodda require.extensions[".ts"] = … kabi "hiylalar" uchraydi. Node hujjatida bu usul eskirgan (deprecated) deb belgilangan. .cjs va .mjs kengaytmalari ro'yxatda alohida yo'q — ularni Node fayl nomi va package.json dagi "type" bo'yicha boshqaradi (ES Modules Node'da).

3. Resolution: Node faylni qanday topadi

3.1 Uch xil yozuv

require ga beriladigan satr — specifier (ko'rsatkich). Uchta turi bor (ESM import darsida brauzer uchun ko'rgansiz):

Specifier Misol Qayerdan qidiriladi
Ichki modul "fs", "node:fs" Node ichidan
Nisbiy / mutlaq "./lib/kurs", "/abs/kurs.js" joriy fayl papkasiga nisbatan
Yalang'och (bare) "kurs-format" node_modules zanjiridan

3.2 Fayl va papka qoidalari

Nisbiy require("./lib/kurs") uchun Node quyidagi tartibda sinaydi (Node hujjatidagi algoritm, soddalashtirilgan):

  1. Aynan lib/kurs fayli.
  2. lib/kurs.js, keyin lib/kurs.json, keyin lib/kurs.node.
  3. lib/kurs — papka bo'lsa: undagi package.json ning "main" maydoni.
  4. Papkada index.js, index.json, index.node.

Buni sinab ko'ramiz. Blok vaqtinchalik papkada kichik tuzilma yaratadi va har require.resolve natijasini (to'liq yo'lni — joriy papkaga nisbatan) chiqaradi. require.resolve faylni yuklamaydi — faqat yo'lni topadi:

js
const { writeFileSync, mkdirSync } = require("node:fs");
const { relative } = require("node:path");

// sinov tuzilmasi: fayl, json, papka (index), package.json "main"
mkdirSync("lib/sana", { recursive: true });
mkdirSync("node_modules/kurs-format", { recursive: true });
writeFileSync("lib/kurs.js", "module.exports = 'kurs.js';");
writeFileSync("lib/sozlama.json", '{ "til": "uz" }');
writeFileSync("lib/sana/index.js", "module.exports = 'index';");
writeFileSync("node_modules/kurs-format/package.json",
  '{ "name": "kurs-format", "main": "asosiy.js" }');
writeFileSync("node_modules/kurs-format/asosiy.js",
  "module.exports = 1;");

const show = (id) =>
  relative(__dirname, require.resolve(id)).replaceAll("\\", "/");
console.log(show("./lib/kurs"));
console.log(show("./lib/sozlama"));
console.log(show("./lib/sana"));
console.log(show("kurs-format"));
console.log(require.resolve("node:fs"), require.resolve("fs"));

Konsolda:

text
lib/kurs.js
lib/sozlama.json
lib/sana/index.js
node_modules/kurs-format/asosiy.js
node:fs fs

To'rtta qoida to'rt qatorda: kengaytma qo'shildi (.js), keyin .json, papka index.js ga, paket esa main ga olib bordi. Ichki modul uchun require.resolve yo'l emas, nomning o'zini qaytaradi. replaceAll("\\", "/") — Windows'dagi teskari chiziqni bir xil ko'rinishga keltirish uchun (path va os darsida chuqur).

Diqqat: Paketning package.json ida "exports" maydoni bo'lsa, u "main" dan ustun. U holda paketning faqat ochiq qilingan fayllarini require qilish mumkin. Buni package.json IV: kirish nuqtalari darsida ko'rgansiz; valyuta da ES Modules Node'da darsida ERR_PACKAGE_PATH_NOT_EXPORTED bilan uchratasiz.

3.3 node_modules zanjiri: module.paths

Yalang'och nomni Node joriy papkadan boshlab yuqoriga qarab har node_modules da qidiradi (node_modules ichida darsidagi "yuqoriga qarab" qoidasi). Bu ro'yxat har modulda tayyor turadi — module.paths. require.resolve.paths(nom) esa aniq nom uchun qidiriladigan papkalarni beradi:

js
const paths = require.resolve.paths("kurs-format");
console.log(paths.length > 2, paths[0].endsWith("node_modules"));
console.log(module.paths[0] === paths[0]);
try {
  require("yoq-paket");
} catch (e) {
  console.log(e.code);
  console.log(e.message.split("\n")[0]);
}

Konsolda:

text
true true
true
MODULE_NOT_FOUND
Cannot find module 'yoq-paket'

To'liq xabar bir necha qatordan iborat: birinchi qatordan keyin Require stack: va qaysi fayl qaysini require qilgani ro'yxati. Stek pastdan yuqoriga o'qiladi: eng pastki — dasturga kirish fayli, eng yuqorisi — topa olmagan fayl. Xato qayerdan kelganini topishda shu ro'yxat eng foydali qism.

Zanjir oxirida yana uchta eski joy qo'shiladi: NODE_PATH muhit o'zgaruvchisidagi papkalar va foydalanuvchi uyidagi .node_modules, .node_libraries. Bular tarixiy, Node hujjati ularga tayanmaslikni tavsiya qiladi.

Tekshirib ko'ring: Papkada kurs.js ham, kurs.json ham bor. require("./kurs") qaysini yuklaydi?

Javob

kurs.js. Kengaytmalar .js → .json → .node tartibida sinaladi, birinchi topilgani olinadi. Chalkashmaslik uchun kengaytmani to'liq yozing: require("./kurs.json"). ESM'da esa kengaytmasiz import umuman ishlamaydi (ES Modules Node'da).

4. Kesh va modul obyekti

4.1 module obyekti ichida nima bor

Har CommonJS fayl o'z module obyektini oladi. Foydali maydonlar:

Maydon Ma'nosi
module.id kesh kaliti; kirish faylida "."
module.filename to'liq yo'l (__filename bilan bir xil)
module.loaded fayl bajarilib bo'ldimi
module.paths node_modules qidiruv zanjiri
module.exports require qaytaradigan qiymat

require.main — dasturga kirish fayli moduli. "Bu fayl to'g'ridan ishga tushirildimi yoki require qilindimi?" degan savolga klassik javob:

js
console.log(require.main === module, module.id, module.loaded);
setImmediate(() => console.log("keyin:", module.loaded));

Konsolda:

text
true . false
keyin: true

Fayl bajarilayotganda loaded — false, tugagach — true. Bu farq keyingi bo'limdagi sikl require'ning kaliti. ESM'da require.main yo'q — Node 24 da uning o'rnida import.meta.main (true/false) bor (ES Modules Node'da).

4.2 JSON ham keshlanadi — va o'zgartirilishi mumkin

CommonJS va ESM bilan o'zaro ishlash darsida JS modul keshini ko'rgansiz. JSON uchun ham xuddi shu qoida va undan kelib chiqadigan tuzoq:

js
const { writeFileSync } = require("node:fs");
writeFileSync("kurs.json", '{ "USD": 11903.15 }');

const a = require("./kurs.json");
a.USD = 0; // "bitta joyda" o'zgartirdik
const b = require("./kurs.json");
console.log(b.USD, a === b);

Konsolda:

text
0 true

Ikkinchi require faylni qayta o'qimadi — keshdagi o'sha obyektni berdi. Dasturning bir burchagida sozlamani o'zgartirsangiz, hamma joyda o'zgaradi. Bundan tashqari, JSON fayl diskda o'zgarsa ham, jarayon qayta ishga tushmaguncha eskisi qoladi. O'zgaruvchan ma'lumot (kurslar keshi) uchun require emas, readFile + JSON.parse ishlating — valyuta aynan shunday qiladi.

5. Sikl (circular) require

5.1 Kanon tajribasi

Sikl bog'liqlik (circular dependency) — a b ni, b esa a ni require qiladi. Kanon tajribasi (fayllar blok ichida yaratiladi):

js
const { writeFileSync } = require("node:fs");
writeFileSync("a.cjs", `
exports.ready = false;
const b = require("./b.cjs");
console.log("a ichida b.ready =", b.ready);
exports.ready = true;
`);
writeFileSync("b.cjs", `
const a = require("./a.cjs");
console.log("b ichida a.ready =", a.ready);
exports.ready = true;
`);
require("./a.cjs");

Konsolda:

text
b ichida a.ready = false
a ichida b.ready = true

5.2 Qadamma-qadam

Qadamlarni sekin kuzatamiz — «require ning besh qadami» bilan:

Qadam Nima bo'ladi a eksporti
1 a.cjs keshga yoziladi va bajarila boshlaydi {}
2 exports.ready = false { ready: false }
3 a → require("./b.cjs"): b keshga, bajarila boshlaydi { ready: false }
4 b → require("./a.cjs"): a keshda bor — bajarilmaydi, joriy eksport beriladi { ready: false }
5 b chiqaradi: a.ready = false; b tugaydi { ready: false }
6 a davom etadi, b.ready = true ni ko'radi; ready = true { ready: true }

Kalit — 4-qadam. a keshga bajarilishdan oldin yozilgan edi. Shuning uchun b cheksiz siklga tushmaydi (a → b → a → …), lekin u a ning yarim tayyor eksportini oladi. Node bu ataylab qilingan kelishuv: sikl xato bermaydi, lekin to'liq ham bo'lmaydi.

5.3 Yomonroq holat: module.exports = {…}

Yuqoridagi misolda b "eski, lekin o'sha" obyektni ushlab qoldi — keyinchalik a.ready ni qayta o'qisa, true ni ko'radi. Fayl module.exports ni almashtirsa esa, b umrbod eski bo'sh obyektga qarab qoladi:

js
const { writeFileSync } = require("node:fs");
writeFileSync("kassa.cjs", `
const narx = require("./narx.cjs");
module.exports = { jami: (n) => n * narx.kurs() };
`);
writeFileSync("narx.cjs", `
const kassa = require("./kassa.cjs");
module.exports = {
  kurs: () => 11903.15,
  tekshir: () => typeof kassa.jami,
};
`);
const kassa = require("./kassa.cjs");
const narx = require("./narx.cjs");
console.log(kassa.jami(2));
console.log(narx.tekshir());

Konsolda:

text
23806.3
undefined

kassa to'liq ishlaydi, narx ichidagi kassa esa bo'sh {} — jami yo'q. narx uni require qilgan paytda kassa hali o'zining yangi module.exports ini yozmagan edi. Keyinroq yozilgan obyekt — boshqa obyekt, narx dagi havola esa eskisiga qaragan.

Node bu holatda yordam beradi. Yuqoridagi natija faqat stdout. Terminalda o'zingiz ishga tushirsangiz, stderr'da ogohlantirish ham chiqadi (biz ishga tushirdik, Node 24.21.0, Windows 11):

text
(node:2212) Warning: Accessing non-existent property 'jami' of module exports inside circular dependency

Tarjimasi: "Sikl bog'liqlik ichida modul eksportining mavjud bo'lmagan jami xususiyatiga murojaat qilindi". Bu ogohlantirishni ko'rsangiz — sikl bor va u ishni buzmoqda.

5.4 Uchta tuzatish

  1. Umumiy qismni ajrating. Ikkala fayl kerak qiladigan narsani (kurs()) uchinchi faylga chiqaring. Sikl yo'qoladi — eng toza yechim.
  2. Kechiktirilgan require. require ni modul yuqorisidan funksiya ichiga ko'chiring. Funksiya chaqirilganda ikkala modul allaqachon to'liq yuklangan bo'ladi.
  3. Eksportni almashtirmang. module.exports = {…} o'rniga exports.jami = … — shunda boshqa modul keyinroq bo'lsa ham to'liq obyektni ko'radi. Bu muammoni yashiradi, yo'q qilmaydi.

Tekshirib ko'ring: Kanon tajribasidagi b.cjs da console.log ni setImmediate(() => console.log(a.ready)) ga o'rasak, nima chiqadi?

Javob

true. setImmediate callback'i hamma sinxron kod tugagach ishlaydi — o'shanda a oxirigacha bajarilgan va exports.ready = true yozilgan. b dagi a — o'sha obyekt (exports almashtirilmagan), shuning uchun yangi qiymat ko'rinadi. Bu 2-tuzatishning ("kechiktirish") boshqa shakli.

6. CLI qadami: holat yo'q

valyuta — ESM loyiha (Global obyektlar darsidagi qaror), shuning uchun uning ichida require yo'q va bu darsdan kod qo'shilmaydi. Kanon o'lchovi shu darsning markaziy faktlarini berdi: Module.wrapper aniq matni, arguments.length = 5, this === module.exports, sikldagi qisman eksport (a.ready = false). Ular yuqoridagi bloklarda.

Lekin CommonJS valyuta dan butunlay uzoq emas. CJS va ESM birga darsida kanon CommonJS loyiha require("valyuta") qila olishini tekshiradi — o'sha yerda bu darsdagi resolution va exports qoidalari ESM bilan uchrashadi.

7. Ko'p uchraydigan xatolar

Xato yoki belgi Sabab Davosi
Error: Cannot find module './kurs' + Require stack noto'g'ri nisbiy yo'l yoki fayl yo'q stekning eng yuqori qatoridagi fayl papkasiga nisbatan tekshiring
Cannot find module 'kurs-format' paket o'rnatilmagan yoki boshqa papkada npm ls kurs-format, require.resolve.paths
TypeError: x.jami is not a function, ba'zan sikl require, yarim tayyor eksport umumiy qismni ajrating
Warning: Accessing non-existent property … inside circular dependency Node siklni sezdi xuddi shu
JSON sozlama "o'zidan" o'zgardi require keshlangan obyektni hamma joyga beradi readFile + JSON.parse yoki structuredClone
Fayl diskda o'zgardi, dastur eskisini ko'radi require.cache qayta ishga tushiring (--watch)

8. Mashqlar

Mashqlar kurs/mashqlar/24/10-cjs/ da. Hammasi .cjs fayllar, terminalda node fayl.cjs.

1-mashq (oson): resolution natijasi

Papkada: kurs.js, kurs.json, util/index.js, util/package.json ({ "main": "asosiy.js" }), util/asosiy.js. Qaysi fayl yuklanadi?

  • require("./kurs") —
  • require("./kurs.json") —
  • require("./util") — util/
  • require("fs") — ichki modul
Yechim
  • kurs.js — .js birinchi sinaladi.
  • kurs.json — kengaytma to'liq yozilgan, aynan shu fayl.
  • asosiy.js — papkada package.json "main" bo'lsa, u index.js dan ustun.
  • node:fs — require("fs") va require("node:fs") bir xil ichki modulni beradi; yangi kodda node: prefiksi tavsiya etiladi — shunda bir xil nomli npm paket bilan adashmaydi.

2-mashq (o'rta): kesh hisoblagichi

hisob.cjs faylini (blok ichida writeFileSync bilan) yarating: u har yuklanganda globalThis.loads ni 1 ga oshirsin va module.exports = { n: globalThis.loads } qilsin. Uni ikki marta require qiling, keyin delete require.cache[require.resolve("./hisob.cjs")] bilan keshdan o'chirib, yana require qiling. Uch natijaning n ini va globalThis.loads ni chiqaring.

Yechim
js
const { writeFileSync } = require("node:fs");
writeFileSync("hisob.cjs",
  "globalThis.loads = (globalThis.loads ?? 0) + 1;\n" +
  "module.exports = { n: globalThis.loads };\n");

const first = require("./hisob.cjs");
const second = require("./hisob.cjs");
delete require.cache[require.resolve("./hisob.cjs")];
const third = require("./hisob.cjs");
console.log(first.n, second.n, third.n, globalThis.loads);
console.log(first === second, second === third);

Konsolda:

text
1 1 2 2
true false

Ikkinchi require keshdan — fayl bajarilmadi, obyekt o'sha. Keshdan o'chirilgach fayl qayta bajarildi va yangi obyekt yaratildi. Hisoblagich globalThis da, chunki modulning ichki o'zgaruvchilari qayta yuklashda nolga qaytadi.

3-mashq (qiyin): siklni tuzating

«Yomonroq holat» blokidagi kassa.cjs va narx.cjs siklini umumiy qismni ajratish usuli bilan tuzating: kurs.cjs yarating (kurs: () => 11903.15), kassa va narx uni ishlatsin, narx endi kassa ni require qilmasin. narx.tekshir() kassa o'rniga typeof kurs.kurs ni qaytarsin. Natija: 23806.3 va function.

Yechim
js
const { writeFileSync } = require("node:fs");
writeFileSync("kurs.cjs",
  "module.exports = { kurs: () => 11903.15 };\n");
writeFileSync("kassa.cjs", `
const kurs = require("./kurs.cjs");
module.exports = { jami: (n) => n * kurs.kurs() };
`);
writeFileSync("narx.cjs", `
const kurs = require("./kurs.cjs");
module.exports = { tekshir: () => typeof kurs.kurs };
`);
const kassa = require("./kassa.cjs");
const narx = require("./narx.cjs");
console.log(kassa.jami(2));
console.log(narx.tekshir());

Konsolda:

text
23806.3
function

Endi bog'liqlik grafi daraxt: kassa → kurs, narx → kurs. Hech bir fayl o'zini bilvosita require qilmaydi, shuning uchun "yarim tayyor" eksport bo'lishi mumkin emas. Real loyihada sikllarni madge --circular kabi vosita bilan topish mumkin (biz sinamadik — nomi ko'rsatkich uchun).

9. Real ishda

  • Stek izlarini o'qish — production xatosida at Module._compile, at Module.load, at Module._load qatorlari ko'rinsa, bu — require bosqichlari. Endi ular "shovqin" emas: xato qaysi fayl yuklanayotganda chiqqanini ko'rsatadi.
  • Sikl bog'liqliklar katta Express va NestJS loyihalarida ko'p uchraydi (servislar bir-birini chaqiradi). NestJS'da buning uchun alohida forwardRef bor — u aynan shu "yarim tayyor" muammoning yechimi.
  • Testlarda kesh — ba'zi test vositalari har testda modulni "toza" yuklash uchun require.cache ni tozalaydi. Vitest va Jest buni o'z modul tizimi bilan qiladi.
  • Intervyu savoli: "CommonJS'da circular require nima qaytaradi?" — xato emas, balki o'sha paytgacha yozilgan qisman module.exports; chunki modul bajarilishidan oldin keshga qo'yiladi.

Xulosa

  • require: resolution → kesh → yangi Module (keshga oldindan) → wrapper ichida bajarish → module.exports.
  • Wrapper — (function (exports, require, module, __filename, __dirname) { … }); Module.wrap bilan ko'rish mumkin.
  • Resolution: aynan fayl → .js/.json/.node → papka (main, index.js) → node_modules zanjiri (module.paths); exports maydoni main dan ustun.
  • require.cache JS'ni ham, JSON'ni ham saqlaydi — bitta obyekt hamma joyda.
  • Sikl require — yarim tayyor eksport; module.exports = {…} bilan bo'sh obyekt. Davosi — umumiy qismni ajratish.

Keyingi dars: ES Modules Node'da — "type": "module", majburiy kengaytmalar, import.meta, top-level await va JSON import — va valyuta ning paket tuzilmasi.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CommonJS ichidan: require qanday ishlaydi — module wrapper, resolution va circular require — IlmHamroh