IlmHamroh
JavaScript Full-stack/16-qism. Frontend asboblari: npm, bundlerlar, config10/48-dars16 daqiqa
Mundarija (26)

node_modules ichida: modul qidirish, hoisting, fantom bog'liqlik va ERESOLVE

Qisqacha: Node import "ms" ni joriy papkadan boshlab yuqoriga qarab har bir node_modules da qidiradi. npm esa paketlarni iloji boricha ildizdagi node_modules ga "ko'taradi" (hoisting), mos kelmagan versiyalarni ichma-ich joylaydi. Shu sababli package.json da yo'q paket ham import qilinadi — bu fantom bog'liqlik. Peer talablari to'qnashganda npm ERESOLVE bilan to'xtaydi. --legacy-peer-deps uni chetlab o'tadi, lekin xato keyinroq, ishlayotgan dasturda chiqadi.

Bu darsda

  • Node paketni qaysi papkalarda va qanday tartibda qidirishini ko'rasiz.
  • Hoisting, ichma-ich nusxalar va deduped belgisini tushunasiz, npm dedupe ishlatasiz.
  • Fantom bog'liqlikni topasiz va u qachon "portlashini" ko'rasiz.
  • ERESOLVE xabarini qatorma-qator o'qiysiz va --legacy-peer-deps ning narxini bilasiz.
  • Ikki nusxa React muammosini o'z ko'zingiz bilan ko'rasiz.

Oldin bilishingiz kerak: Lock-fayllar va npm ci, package.json II: bog'liqlik turlari, npm buyruqlari chuqur.

1. Nega bu kerak?

vazifalar ning package.json ida 8 ta paket, node_modules da esa 102 ta, hajmi 86 MB. Sardor sinab ko'rdi: ms paketi package.json da yo'q, lekin u ishlaydi:

bash
node --input-type=module \
  -e "import ms from 'ms'; console.log(ms('1d'))"
text
86400000

Bir kunlik millisekundlar. O'rnatilmagan paket qanday ishladi? Yana bir savol bog'liqlik turlari darsidan qolgan: typescript-eslint ni TypeScript 7 bilan o'rnatib bo'lmadi — ERESOLVE. Internetdagi maslahat esa bitta: "--legacy-peer-deps qo'shing". Qo'shsa nima bo'ladi?

Ikkala javob node_modules ning tuzilishida. Bugun uning ichiga kiramiz.

Maslahat: Chiqishlar 2026-10-10 da Windows 11, Node 24.21.0 va npm 11.19.0 bilan olingan. Yo'l boshi … bilan qisqartirilgan.

2. Node paketni qanday qidiradi

2.1 Yuqoriga qarab

kurs/mashqlar/16/10-node-modules/kassa/ da src/hisob/vaqt.js:

js
// vaqt.js — ms paketini ichki papkadan ishlatadi
import ms from "ms";

console.log("2 soat =", ms("2h"), "ms");

Fayl ikki papka chuqurlikda, node_modules esa loyiha ildizida. Node qaysi papkalarga qaraydi? require.resolve.paths buni aytadi (src/hisob ichida turib):

bash
node -p "require.resolve.paths('ms')"
text
[
  '…\\kurs\\mashqlar\\16\\10-node-modules\\kassa\\src\\hisob\\node_modules',
  '…\\kurs\\mashqlar\\16\\10-node-modules\\kassa\\src\\node_modules',
  '…\\kurs\\mashqlar\\16\\10-node-modules\\kassa\\node_modules',
  '…\\kurs\\mashqlar\\16\\10-node-modules\\node_modules',
  '…\\kurs\\mashqlar\\16\\node_modules',
  …
  'C:\\node_modules',
  'C:\\Users\\<ism>\\.node_modules',
  'C:\\Users\\<ism>\\.node_libraries',
  …
]

(Ro'yxat qisqartirildi: bizda 17 ta yo'l.) Qoida: joriy papkadan boshlab, har bir ota papkaga node_modules qo'shib, disk ildizigacha. Birinchi topilgani ishlatiladi. Oxirgi uchtasi — eski global papkalar, ularni faqat require ko'radi.

flowchart TD
  A["kassa/src/hisob/vaqt.js<br/>import 'ms'"] --> B["src/hisob/node_modules — yo'q"]
  B --> C["src/node_modules — yo'q"]
  C --> D["kassa/node_modules/ms — bor!"]
  D --> E["package.json → exports → fayl"]
  C -. "topilmasa" .-> F["ota papkalar … disk ildizi"]
  F -.-> G["ERR_MODULE_NOT_FOUND"]

Papka topilgach, qaysi fayl ochilishini kirish nuqtalari darsidagi exports va main hal qiladi.

2.2 Tuzoq: ota papkadagi node_modules

"Disk ildizigacha" degani — loyihadan tashqarida ham. Sinov: kassa da picocolors yo'q, rang.js uni import qiladi:

js
// rang.js — package.json da yo'q paketni import qiladi
import pc from "picocolors";

console.log(pc.green("Osh tayyor"), "| picocolors qayerdan?");

Avval ERR_MODULE_NOT_FOUND. Endi bir papka yuqorida (10-node-modules/) npm i picocolors qildik:

bash
node rang.js
node -p "require.resolve('picocolors')"
text
Osh tayyor | picocolors qayerdan?
…\kurs\mashqlar\16\10-node-modules\node_modules\picocolors\picocolors.js

Ishladi — loyihaga tegishli bo'lmagan papkadan. npm ls picocolors esa (empty) deydi va 1 bilan tugaydi: npm faqat o'z loyihasini biladi. Bunday xato faqat sizning kompyuteringizda "ishlaydi", CI'da esa — yo'q. Qoida: loyihalarni bir-birining ichiga qo'ymang va uy papkangizda (C:\Users\<ism>) tasodifan npm install qilmang.

Tekshirib ko'ring: D:\loyihalar\node_modules\vite bor. D:\loyihalar\bahor\ da Vite o'rnatilmagan, src/main.js esa import "vite" qiladi. Nima bo'ladi?

Javob

Ishlaydi: Node bahor/src/node_modules, bahor/node_modules dan keyin D:\loyihalar\node_modules ga ham qaraydi va Vite'ni topadi. Lekin bu loyiha boshqa kompyuterda sinadi. npm ls vite esa yo'qligini ko'rsatadi. Yechim — npm i -D vite va ota papkadagi node_modules ni o'chirish.

3. Hoisting: npm paketlarni qayerga qo'yadi

3.1 Ko'tarish

Agar har paket o'z bog'liqliklarini o'z papkasiga qo'ysa (eslint/node_modules/debug/node_modules/ms/…), daraxt juda chuqur bo'lardi va bir paket o'nlab marta takrorlanardi. npm 3 dan beri boshqacha: iloji bo'lsa, paketni ildizdagi node_modules ga qo'yadi. Bu hoisting (ko'tarish). O'tgan darslarda ko'rgan deduped belgisi — "takror nusxa qo'yilmadi, ildizdagisi ishlatiladi".

3.2 Mos kelmasa — ichma-ich

kassa da: npm i -E debug@4.4.3 ms@2.0.0. debug o'zi ms@^2.1.3 ni so'raydi, biz esa ildizga 2.0.0 ni qo'ydik:

bash
npm ls ms
text
kassa@1.0.0 …\kurs\mashqlar\16\10-node-modules\kassa
+-- debug@4.4.3
| `-- ms@2.1.3
`-- ms@2.0.0
bash
ls node_modules node_modules/debug/node_modules
text
node_modules:
debug
ms

node_modules/debug/node_modules:
ms

Ildizda — bizning ms@2.0.0. debug ga u mos emas, shuning uchun 2.1.3 debug ning ichiga qo'yildi. Node qidiruvi buni o'zi hal qiladi: debug ichidagi import "ms" avval debug/node_modules ga qaraydi va 2.1.3 ni topadi. Bizning kodimiz esa ildizdagi 2.0.0 ni oladi. Ikkalasi baxtli — lekin diskda ikki nusxa.

3.3 Dublikatlar: muqarrar va keraksiz

Ba'zi takrorlar muqarrar. Express 4.22.3 ni o'rnatsak:

bash
npm ls ms
text
dublikat@1.0.0 …\kurs\mashqlar\16\10-node-modules\dublikat
`-- express@4.22.3
  +-- debug@2.6.9
  | `-- ms@2.0.0
  `-- send@0.19.2
    `-- ms@2.1.3

debug@2.6.9 aynan ms@2.0.0 ni, send esa 2.1.3 ni talab qiladi. Bitta versiya ikkalasini qondira olmaydi. npm find-dupes ("takrorlarni top") bu yerda hech narsa taklif qilmaydi.

Keraksiz takror esa bunday paydo bo'ladi. dedupe/ da avval debug@4.4.3 (u ms@2.1.3 ni olib keldi), keyin npm i ms@2.1.2 — package.json ga "^2.1.2" yozildi:

bash
npm ls ms
text
dedupe@1.0.0 …\kurs\mashqlar\16\10-node-modules\dedupe
+-- debug@4.4.3
| `-- ms@2.1.3
`-- ms@2.1.2

Ikki nusxa — lekin 2.1.3 bizning ^2.1.2 ga ham mos! npm ularni o'zi birlashtirmadi: o'rnatish paytida faqat so'ralgan narsani qo'ydi.

bash
npm find-dupes
text
change ms 2.1.2 => 2.1.3
remove ms 2.1.3

removed 1 package, and changed 1 package in 485ms

find-dupes — "quruq mashq": nima qilishini aytadi, diskka tegmaydi. Haqiqatan bajarish — npm dedupe:

bash
npm dedupe
npm ls ms
text

removed 1 package, changed 1 package, and audited 3 packages in 1s

found 0 vulnerabilities
dedupe@1.0.0 …\kurs\mashqlar\16\10-node-modules\dedupe
+-- debug@4.4.3
| `-- ms@2.1.3 deduped
`-- ms@2.1.3

Bitta nusxa, deduped. Katta loyihalarda npm dedupe lock-faylni sezilarli kichraytirishi mumkin. Lekin u versiyalarni o'zgartiradi — keyin testlarni yuriting.

Tekshirib ko'ring: Express misolida ms ning ikki nusxasi bor. Bu muammomi?

Javob

Odatda yo'q: ms — holatsiz kichik funksiya, ikki nusxa faqat bir necha KB disk. Muammo nusxa holat saqlaganda boshlanadi — masalan, React. Ikki nusxa bir-birining ichki ma'lumotini ko'rmaydi («Ikki nusxa React» bo'limi).

4. Fantom bog'liqlik

4.1 Nima u

Hoisting'ning yon ta'siri: ildizdagi node_modules da siz so'ramagan paketlar ham turadi. Node esa package.json ga qaramaydi — u faqat papkani qidiradi. Natijada siz e'lon qilinmagan paketni import qila olasiz. Bu phantom dependency (fantom bog'liqlik) — "arvoh": bor, lekin hujjatda yo'q. «Nega bu kerak?» bo'limidagi ms aynan shunday: uni eslint → debug olib kelgan.

4.2 Qachon portlaydi

fantom/ da faqat npm i -D -E eslint@10.12.0. Kod esa debug ni ishlatadi:

js
// log.js — debug paketini package.json ga yozmasdan ishlatadi
import createDebug from "debug";

const log = createDebug("bahor:kassa");
log.enabled = true;
log("buyurtma qabul qilindi");
bash
node log.js
text
2026-10-10T15:04:45.819Z bahor:kassa buyurtma qabul qilindi

Ishlaydi (terminalda vaqt o'rniga rangli +0ms chiqadi). npm ls debug sababni ko'rsatadi:

text
fantom@1.0.0 …\kurs\mashqlar\16\10-node-modules\fantom
`-- eslint@10.12.0
  +-- @eslint/config-array@0.23.5
  | `-- debug@4.4.3 deduped
  `-- debug@4.4.3

Serverda esa (bog'liqlik turlari darsidagi --omit=dev):

bash
npm ci --omit=dev
node log.js
text
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'debug' imported from …\kurs\mashqlar\16\10-node-modules\fantom\log.js

ESLint o'rnatilmadi — u bilan birga "arvoh" ham ketdi. Fantom bog'liqlik yana uch holatda portlaydi: ESLint yangi versiyada debug dan voz kechsa; debug ning boshqa MAJOR versiyasini olib kelsa; yoki loyiha pnpm'ga o'tsa — pnpm fantomlarni umuman ko'rsatmaydi (pnpm).

Davosi: ishlatayotgan har paketni o'zingiz e'lon qiling — npm i -P -E debug@4.4.3. Topish uchun: bog'liqlik turlari darsidagi tekshiruvchi skript, ESLint qoidalari va knip (knip darsi).

5. ERESOLVE: peer to'qnashuvi

5.1 Xabarni o'qish

Bog'liqlik turlari darsidagi xato — TypeScript 7.0.2 o'rnatilgan loyihaga typescript-eslint@8.71.1:

text
npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
npm error
npm error While resolving: t10a@1.0.0
npm error Found: typescript@7.0.2
npm error node_modules/typescript
npm error   dev typescript@"7.0.2" from the root project
npm error
npm error Could not resolve dependency:
npm error peer typescript@">=4.8.4 <6.1.0" from typescript-eslint@8.71.1
npm error node_modules/typescript-eslint
npm error   dev typescript-eslint@"8.71.1" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry this command with --force or --legacy-peer-deps to accept an incorrect (and potentially broken) dependency resolution.
npm error
npm error
npm error For a full report see:
npm error …\npm-cache\_logs\2026-10-07T06_40_49_672Z-eresolve-report.txt

Uch qismga bo'lib o'qiymiz:

Qism Qatorlar Ma'nosi
While resolving t10a@1.0.0 kimning daraxtini qurayotgandim
Found typescript@7.0.2 … from the root project daraxtda nima bor va kim so'ragan
Could not resolve peer typescript@">=4.8.4 <6.1.0" qaysi talab bajarilmadi

Oxirgi gap — tavsiya: "Yuqoridagi to'qnashuvni tuzating yoki --force yoki --legacy-peer-deps bilan qayta urining". Bayroqlar nima uchun? "Noto'g'ri (va ehtimol buzilgan) daraxtni qabul qilish uchun". npm o'zi ogohlantirmoqda: bu bayroqlar muammoni hal qilmaydi, faqat ko'zni yumadi. eresolve-report.txt — to'liq hisobot fayli.

5.2 --legacy-peer-deps ning narxi

Baribir sinab ko'ramiz. peer/ da TypeScript 7.0.2 va ESLint 10.12.0 bor:

bash
npm i -D -E typescript-eslint@8.71.1 --legacy-peer-deps
text

added 17 packages, and audited 97 packages in 2m

29 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

O'rnatildi. --legacy-peer-deps — "npm 6 dagidek: peer talablariga e'tibor berma". Lekin npm ls typescript haqiqatni aytadi: npm error invalid: typescript@7.0.2 …. Oddiy eslint.config.js (recommendedTypeChecked) bilan bitta .ts faylni tekshiramiz:

bash
npx eslint narx.ts
text
typescript-eslint does not support TS 7.0.
Please see https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/#running-side-by-side-with-typescript-6.0 to run typescript-eslint using the TS 6 API.
See also https://github.com/typescript-eslint/typescript-eslint/issues/10940 for tracking typescript-eslint's support for TS >=7.1

Oops! Something went wrong! :(

ESLint: 10.12.0

Error: typescript-eslint does not support TS 7.0.
…

"typescript-eslint TS 7.0 ni qo'llamaydi. TypeScript 6 API bilan yonma-yon ishlatish uchun — havola". Peer talabi bejiz yozilmagan edi: plagin TypeScript'ning ichki API'siga tayanadi, TS 7 da esa u yo'q. ERESOLVE o'rnatishda, ya'ni eng arzon joyda ogohlantirgan edi. Bayroq xatoni ishlayotgan asbobga ko'chirdi.

--force ham shunga o'xshaydi, faqat yanada qo'pol: u to'qnashuvda ham, boshqa himoyalarda ham to'xtamaydi. --strict-peer-deps esa aksincha — hatto ogohlantirishni ham xatoga aylantiradi.

5.3 To'g'ri yechimlar

  1. Mos versiyalarni tanlang. npm view typescript-eslint peerDependencies — qaysi TypeScript kerak. Bizda: <6.1.0.
  2. Ikkala versiyani yonma-yon saqlang. Xabardagi havola aynan shuni taklif qiladi. vazifalar 15-qismdan beri shunday: @typescript/native — TS 7 (tsc uchun), typescript — TS 6 (ESLint uchun), taxallus bilan (npm:).
  3. Plagin yangilanishini kuting yoki uning issue'sini kuzating.
  4. Vaqtincha va ongli ravishda — overrides. Hech qachon "jim bo'lsin" uchun --legacy-peer-deps ni .npmrc ga yozmang: u barcha kelajakdagi to'qnashuvlarni ham yashiradi.
flowchart LR
  E["ERESOLVE"] --> V["npm view … peerDependencies"]
  V --> M{"mos versiya bormi?"}
  M -- "ha" --> U["o'sha versiyani o'rnating"]
  M -- "yo'q" --> Y["yonma-yon (taxallus)<br/>yoki kuting"]
  E -. "--legacy-peer-deps" .-> X["o'rnatildi, lekin<br/>ishlaganda buziladi"]

Tekshirib ko'ring: Hamkasbingiz README'ga yozibdi: "O'rnatish: npm install --legacy-peer-deps". Bu loyiha haqida nima deydi?

Javob

Loyihada hal qilinmagan peer to'qnashuvi bor: qaysidir plagin o'zi qo'llamaydigan versiya bilan ishlayapti. Ehtimol hozircha ishlaydi, lekin kafolat yo'q. npm ls dagi invalid qatorlarini toping va to'qnashuvni yeching — shunda bayroq ham kerak bo'lmaydi.

6. Ikki nusxa React

Fantomdan ham xavfliroq holat — holatli paketning ikki nusxasi. Klassik misol — React (17-qismda o'rganamiz; hozir bilish shart emas: u interfeys qismlarini — "komponentlar"ni — chizadigan kutubxona). React o'z ichida "hozir qaysi komponent chizilyapti" degan yagona holatni saqlaydi.

Sardor «Bahor» tugmasini alohida bahor-ui paketiga chiqardi. Paketni sinash uchun uning ichiga ham React o'rnatdi (devDependencies). Saytda esa npm i ../bahor-ui — paket papkadan, kirish nuqtalari darsidagidek havola bilan ulandi.

js
// tugma.js — «Bahor» tugmasi: necha marta bosilganini eslaydi
import { createElement, useState } from "react";

export function OrderButton() {
  const [count] = useState(0);
  return createElement("button", null, `Buyurtma (${count})`);
}

Sayt tugmani HTML qatoriga aylantiradi (React 19.3.0, react-dom/server):

bash
node render.js
text
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.
…\ikki-react\bahor-ui\node_modules\react\cjs\react.development.js:1309
      return resolveDispatcher().useState(initialState);
                                ^

TypeError: Cannot read properties of null (reading 'useState')

Xabarning uchinchi sababi — bizniki: "ilovada React'ning bir nechta nusxasi bo'lishi mumkin". Yo'lga qarang: bahor-ui\node_modules\react — sayt React'ni emas, paket ichidagi nusxani ishlatdi. Node qidiruvi tugma.js turgan joydan boshlandi va birinchi node_modules/react ni topdi. react-dom esa saytning React'iga ulangan. Ikki nusxa — ikki xil "joriy komponent" holati.

Birinchi qadam — bog'liqlik turlari darsidagi qoida: bahor-ui React'ni peerDependencies da e'lon qiladi (bizda shunday). Lekin bu yetmadi. Sinov uchun bahor-ui/node_modules ni olib qo'ydik — endi Cannot find package 'react' imported from …\bahor-ui\tugma.js (ERR_MODULE_NOT_FOUND). Nega? file: havola (symlink) bo'lgani uchun Node tugma.js ning haqiqiy joyidan qidiradi — bahor-ui papkasi saytning yonida turibdi, ichida emas.

Ishlaydigan yechim — paketni havola emas, nusxa qilib o'rnatish:

bash
npm i ../bahor-ui --install-links
node render.js
text

changed 1 package, and audited 5 packages in 2s

found 0 vulnerabilities
<button>Buyurtma (0)</button>

--install-links — "file: paketni arxivga yig'ib, nusxa sifatida qo'y" (xuddi registrdan kelgandek; node_modules arxivga tushmaydi). Endi bahor-ui sayt ichida, uning import "react" i saytning yagona React'ini topdi. Monorepo va npm link bilan ishlaganda bu muammo ayniqsa ko'p chiqadi (Begona paketni tuzatish); bundler'larda buning uchun alohida sozlama bor (Vite'da resolve.dedupe).

7. Ko'p uchraydigan xatolar

Xabar / belgi Sabab Davosi
ERESOLVE unable to resolve dependency tree peer diapazoniga mos emas mos versiya yoki yonma-yon
invalid: "…" from … (npm ls) --legacy-peer-deps yoki override to'qnashuvni yeching
Invalid hook call React'ning ikki nusxasi peer + ichki nusxani o'chirish
ERR_MODULE_NOT_FOUND faqat serverda fantom bog'liqlik paketni e'lon qiling
Xabar / belgi Sabab Davosi
e'lon qilinmagan paket ishlayapti hoisting yoki ota papka npm ls nom, require.resolve
bir paketning ikki nusxasi diapazonlar kesishmaydi yoki takror npm find-dupes, npm dedupe
typescript-eslint does not support TS 7.0 peer talabi chetlab o'tilgan TS 6 API'ni yonma-yon

8. Mashqlar

Mashqlar kurs/mashqlar/16/10-node-modules/ da.

1-mashq (oson): Daraxtni o'qing

«Dublikatlar» bo'limidagi Express daraxtiga qarab javob bering:

  • send qaysi ms ni ishlatadi?
  • debug@2.6.9 qaysi ms ni ishlatadi?
  • Ildizdagi node_modules/ms qaysi versiya bo'lishi mumkin? npm ls ms --parseable bilan tekshiring.
Yechim

--parseable daraxt o'rniga diskdagi yo'llarni beradi. Bizda Express 4.22.3 da ildizda ms@2.0.0, send/node_modules/ms da esa 2.1.3 turibdi — npm ko'proq so'ralgan versiyani ko'taradi. Sizda (boshqa Express versiyasida) tartib boshqacha bo'lishi mumkin — qoida bir xil: har paket o'ziga eng yaqin node_modules dagi nusxani oladi.

2-mashq (o'rta): Arvohni tuting

fantom/ da (eslint faqat dev'da, log.js darsdagidek):

  1. npm ci --omit=dev va node log.js. Xato:
  2. Bitta buyruq bilan tuzating va 1-qadamni takrorlang.
Yechim

npm i -P -E debug@4.4.3. Endi package.json:

json
{
  "dependencies": {
    "debug": "4.4.3"
  },
  "devDependencies": {
    "eslint": "10.12.0"
  }
}

npm ci --omit=dev, node log.js:

text
2026-10-10T15:04:45.819Z bahor:kassa buyurtma qabul qilindi

Vaqt sizda boshqacha. Endi debug ESLint'ga bog'liq emas.

3-mashq (o'rta): Takrorni yo'qoting

dedupe/ papkasida darsdagi holatni yarating (debug@4.4.3, keyin ms@2.1.2). npm find-dupes nima taklif qiladi? npm dedupe dan keyin npm ls ms da qaysi so'z paydo bo'ladi:

Yechim

find-dupes: change ms 2.1.2 => 2.1.3, remove ms 2.1.3. npm dedupe — removed 1 package, changed 1 package. Keyin npm ls ms: ms@2.1.3 deduped va ildizda ms@2.1.3. package.json o'zgarmadi ("^2.1.2") — 2.1.3 bu diapazonga mos, faqat lock va disk o'zgardi.

4-mashq (qiyin): Node qidiruvini takrorlang

qidiruv/yollar.mjs da lookupPaths(dir) yozing — dir papkasidan disk ildizigacha node_modules yo'llari ro'yxati, Node bilan bir xil tartibda. Nomi node_modules bo'lgan papkaga yana node_modules qo'shilmaydi. yollar.test.mjs da natijani Node'ning o'zi bilan solishtiring: createRequire(fayl).resolve.paths("ms").

Ishoralar: path.dirname — ota papka; disk ildizida path.dirname(x) === x. path.basename — oxirgi qism. createRequire — ESM fayldan require yaratadi (CommonJS va ESM).

Yechim

yollar.mjs:

js
// yollar.mjs — Node paketni qaysi node_modules larda qidiradi?
import path from "node:path";

// dir — import yozilgan fayl turgan papka (absolyut yo'l)
export function lookupPaths(dir) {
  const result = [];
  let current = path.resolve(dir);
  while (true) {
    // node_modules ichida yana node_modules/node_modules qidirilmaydi
    if (path.basename(current) !== "node_modules") {
      result.push(path.join(current, "node_modules"));
    }
    const parent = path.dirname(current);
    if (parent === current) break; // disk ildiziga yetdik
    current = parent;
  }
  return result;
}

yollar.test.mjs:

js
// yollar.test.mjs — natijani Node'ning o'zi bilan solishtiradi
import { test } from "node:test";
import assert from "node:assert/strict";
import { createRequire } from "node:module";
import path from "node:path";
import { lookupPaths } from "./yollar.mjs";

// Node ro'yxati oxiriga global papkalarni (~/.node_modules)
// qo'shadi — ularni solishtirmaymiz
function nodePaths(dir) {
  const req = createRequire(path.join(dir, "fayl.js"));
  const all = req.resolve.paths("ms");
  return all.slice(0, lookupPaths(dir).length);
}

test("Node bilan bir xil tartib", () => {
  const dirs = [
    process.cwd(),
    path.join(process.cwd(), "src", "hisob"),
    path.join(process.cwd(), "node_modules", "debug", "src"),
  ];
  for (const dir of dirs) {
    assert.deepEqual(lookupPaths(dir), nodePaths(dir), dir);
  }
});

test("birinchi — eng yaqin papka, oxirgi — disk ildizi", () => {
  const list = lookupPaths(path.join(process.cwd(), "src"));
  const src = path.join(process.cwd(), "src");
  assert.equal(list[0], path.join(src, "node_modules"));
  assert.equal(path.dirname(list.at(-1)), path.parse(list[0]).root);
});
text
ℹ tests 2
ℹ pass 2
ℹ fail 0

Uchinchi papka (node_modules/debug/src) — node_modules ni o'tkazib yuborish qoidasining sinovi: Node …/node_modules/node_modules ni qidirmaydi. Testlar papkalar mavjud bo'lmasa ham ishlaydi — Node ham, bizning funksiya ham faqat yo'l bilan hisoblaydi.

9. Real ishda

  • "Menda ishlaydi" xatolarining katta qismi — fantom bog'liqlik yoki ota papkadagi node_modules. Birinchi savol: "npm ls <nom> nima deydi?".
  • ERESOLVE — yangi plagin o'rnatishda eng ko'p uchraydigan xato. Professional javob: npm view … peerDependencies, keyin qaror. --legacy-peer-deps — oxirgi chora, sababi yozilgan holda.
  • Ikki nusxa React/Vue — monorepo va npm link dagi klassik muammo; bundler'larda resolve.dedupe sozlamasi aynan shuning uchun bor (Vite darslarida).
  • Intervyu: "hoisting nima?", "phantom dependency qanday paydo bo'ladi?", "--legacy-peer-deps nima qiladi va nega xavfli?".

Xulosa

  • Node paketni joriy papkadan disk ildizigacha har node_modules da qidiradi; birinchi topilgani ishlatiladi — loyihadan tashqaridagisi ham.
  • npm paketlarni ildizga ko'taradi (hoisting); mos kelmagan versiya ichma-ich joylashadi; deduped — takror qo'yilmagan.
  • npm find-dupes — keraksiz takrorlarni ko'rsatadi, npm dedupe — tuzatadi; kesishmaydigan diapazonlarda takror muqarrar.
  • Fantom bog'liqlik — e'lon qilinmagan, lekin hoisting tufayli ishlayotgan paket; --omit=dev, yangilanish yoki pnpm'da portlaydi.
  • ERESOLVE: Found — bor narsa, Could not resolve — bajarilmagan peer talabi. --legacy-peer-deps xatoni o'rnatishdan ishlayotgan asbobga ko'chiradi.
  • Holatli kutubxonaning (React) ikki nusxasi — Invalid hook call; yechim — peer va bitta nusxa.

Keyingi dars: npx, npm create va bir martalik CLI'lar — paketni o'rnatmasdan ishga tushirish, npm create vite@latest va @latest ning xavfi.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
nodemodules ichida: modul qidirish, hoisting, fantom bog'liqlik va ERESOLVE — IlmHamroh