IlmHamroh
JavaScript Full-stack/16-qism. Frontend asboblari: npm, bundlerlar, config48/48-dars15 daqiqa
Mundarija (25)

knip: ishlatilmagan fayl, eksport va bog'liqliklarni topish

Qisqacha: knip — loyihadagi "o'lik" narsalarni topadigan vosita: hech kim import qilmaydigan fayllar, hech kim ishlatmaydigan eksport va turlar, package.json da turgan, lekin kodda yo'q paketlar va aksincha. U Vite, ESLint, commitlint, husky kabi asboblarni plaginlar orqali taniydi, shuning uchun sozlamasiz ham to'g'ri ishlaydi. vazifalar da knip 3 ta ishlatilmagan tur eksportini topdi — ulardan biri 15-qismda yozgan ApiKlient imiz.

Bu darsda

  • knip nima qidirishini va hisobot bo'limlarini (Unused files, Unused exports, Unlisted dependencies…) o'qiy olasiz.
  • vazifalar da knip'ni ishga tushirib, topilmalarni tahlil qilasiz va tuzatasiz.
  • Har topilmani "o'chirish" yoki "export'ni olish" deb to'g'ri ajratasiz.
  • knip.json ni minimal sozlaysiz va knip'ning maslahatlarini (configuration hints) o'qiysiz.
  • depcheck, madge, dependency-cruiser va ts-prune bilan farqini bilasiz.

Oldin bilishingiz kerak: Kutubxona manba kodini o'qish, Utility types, package.json II: bog'liqlik turlari.

1. Nega bu kerak?

O'tgan darsda begona kodni o'qidik. Endi o'z kodimizga qaraymiz. vazifalar 08-qismdan beri o'sib keldi: funksiyalar qo'shildi, ko'chirildi, qayta yozildi. Har o'zgarishda biror narsa "qolib ketishi" mumkin: endi chaqirilmaydigan funksiya, hech kim import qilmaydigan tur, keraksiz bo'lib qolgan paket.

Bunday kod zarar keltiradimi? Ha, sekin-asta:

  • O'qish qiyinlashadi. Yangi dasturchi ApiKlient turini ko'rib, "bu qayerda ishlatiladi?" deb vaqt sarflaydi.
  • O'zgartirish qo'rqinchli. "Kimdir buni ishlatayotgan bo'lsa-chi?" — va hech kim o'chirmaydi.
  • Keraksiz paket — npm install vaqti, ta'minot zanjiri xavfi, yangilash ishi.

Oshxona omboriga o'xshatamiz: yillar davomida "balki kerak bo'lar" deb qoldirilgan idishlar joy egallaydi va kerakli narsani topishni qiyinlashtiradi. Vaqti-vaqti bilan inventarizatsiya kerak. knip — kod uchun inventarizatsiya.

O'lik kod (dead code) — bajarilmaydigan yoki hech qayerdan chaqirilmaydigan kod. Tree shaking uni build natijasidan olib tashlaydi, lekin manba kodda u qolaveradi. knip aynan manbani tozalashga yordam beradi.

2. knip qanday ishlaydi

flowchart LR
  P["package.json<br/>scripts, deps"] --> K["knip"]
  C["config fayllar<br/>(plaginlar)"] --> K
  K --> E["kirish nuqtalari<br/>(entry)"]
  E --> G["import grafi"]
  G --> R["hisobot:<br/>topilmagan narsalar"]
  1. Kirish nuqtalarini topadi: package.json dagi main/exports/scripts, index.html, vite.config.ts, testlar.
  2. Ulardan import grafini quradi — bundler kabi: kim kimni import qiladi.
  3. Grafga tushmagan hamma narsani hisobot qiladi: fayllar, eksportlar, paketlar.

Ikkinchi qadam bundler'nikiga o'xshaydi, farqi — maqsadda: Vite grafni yig'ish uchun quradi, knip esa grafdan tashqarida qolganni topish uchun.

2.1 Plaginlar — knip'ning kuchi

Loyihada ko'p fayl import orqali emas, asbob orqali ishlatiladi: commitlint.config.js ni commitlint o'qiydi, .lintstagedrc.json ni lint-staged, vite.config.ts ni Vite. Oddiy import grafida ular "hech kim ishlatmaydigan" bo'lib ko'rinardi. knip'da 100 dan ortiq plagin bor: Vite, ESLint, commitlint, husky, lint-staged, node:test va boshqalar. Har plagin o'z asbobining config faylini o'qiydi. Undan kirish nuqtalari va ishlatilgan paketlar olinadi. Plagin package.json da asbob borligini ko'rsa, o'zi yoqiladi.

3. Vazifalar qadami: knip

3.1 O'rnatish va birinchi ishga tushirish

Branch: chore/knip.

bash
npm i -D knip@6.40.0
text

added 17 packages, and audited 221 packages in 8s

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

found 0 vulnerabilities

Versiya — kanon 6.40.0 (bu dars yozilayotganda 6.41.0 ham chiqdi — npm view knip version; farqi bizga ta'sir qilmaydi).

bash
npx knip
text
Unused exported types (3)
YangiVazifa  type  src/api.ts:22:13   
ApiKlient    type  src/api.ts:216:13  
Amal         type  src/render.ts:78:13

Chiqish kodi 1. Birinchi ishga tushirish bizda 33 s davom etdi, ikkinchisi — 1.9 s (sizda boshqacha bo'ladi). Hech qanday sozlama yozmadik. knip package.json dagi Vite, ESLint, commitlint, husky, lint-staged va node --test ni tanidi va ularning fayllarini to'g'ri hisobladi. Natija: fayllar, paketlar bo'yicha — toza. Faqat uchta tur eksporti ishlatilmagan.

3.2 Hisobotni o'qish

Ustun ApiKlient qatorida Ma'nosi
1 ApiKlient nom
2 type turi: tur (type), funksiya, klass…
3 src/api.ts:216:13 fayl, qator, ustun

"Unused exported types" — "ishlatilmagan eksport qilingan turlar". Diqqat: tur ishlatilmagan emas, uning eksporti ishlatilmagan. Ya'ni boshqa fayl uni import qilmaydi. Fayl ichida ishlatilishi mumkin.

3.3 Uchta topilma — ikki xil qaror

Har birini ochib qaraymiz.

YangiVazifa (api.ts:22) — Utility types qadamida yozgan tur:

ts
export type YangiVazifa = Pick<VazifaMalumoti, "matn">;

api.ts ichida POST so'rov tanasi uchun ishlatiladi. Faqat tashqariga kerak emas. Qaror: export ni olib tashlash, turni qoldirish.

Amal (render.ts:78) — tugma amallari ro'yxati ("almashtir" | "ochir" | …). Xuddi shunday: ichkarida ishlatiladi, tashqarida — yo'q. export olib tashlandi.

ApiKlient (api.ts:216) — eng qiziq:

ts
/** Klient obyektining turi — funksiyadan chiqarib olinadi */
export type ApiKlient = ReturnType<typeof apiKlient>;

Uni Utility types darsida ReturnType ni o'rganganda yozgandik, infer darsida esa uning ichida infer R turganini ko'rgandik. O'shanda chiroyli misol edi. Endi knip so'raydi: "Buni kim ishlatadi?" Javob — hech kim: api.ts ichida ham, boshqa faylda ham. Qaror: o'chirish. Misol darslarda qoladi — kodda esa unga ehtiyoj yo'q.

Bu — darsning asosiy saboqi. O'rganish uchun yozilgan kod real loyihada "qolib ketadi". U ishlaydi, xato bermaydi, testlar o'tadi — shuning uchun hech kim sezmaydi. Avtomatik vosita esa sezadi.

Tekshirib ko'ring: Nega YangiVazifa ni o'chirmadik, ApiKlient ni esa o'chirdik? Ikkalasi ham "Unused exported types" da edi.

Javob

Hisobot faqat eksport ishlatilmaganini aytadi. YangiVazifa api.ts ichida ishlatiladi — u kerak, faqat tashqariga ochiq bo'lishi shart emas. ApiKlient esa faylning ichida ham ishlatilmaydi — u butunlay ortiqcha. Har topilmani ochib qarash kerak: knip "nima" ni aytadi, "nima qilish" ni — siz.

3.4 Tuzatish va natija

api.ts:

ts
type YangiVazifa = Pick<VazifaMalumoti, "matn">;

ApiKlient va uning izohi o'chirildi. render.ts:

ts
type Amal = "almashtir" | "ochir" | "tahrirla" | "saqla" | "bekor";

(Prettier qatorni birlashtirdi — export siz u 72 belgiga sig'di.) package.json ga skript: "knip": "knip".

bash
npx knip

Buyruq jim tugaydi (chiqish yo'q, chiqish kodi 0) — bu muvaffaqiyat belgisi. npx tsc -b — toza, npm test — 146/146, build hash'i o'zgarmadi: biz faqat turlarni o'zgartirdik, ular JavaScript'da yo'q (TypeScript build).

Nega CI'da emas? npm run check ga knip qo'shilmadi. knip topilmalari ko'pincha qaror talab qiladi (o'chirishmi yoki eksportni olishmi?) va yangi funksiya yozilayotganda vaqtincha "ishlatilmagan" eksport normal holat. Shuning uchun npm run knip — vaqti-vaqti bilan, masalan, har qism oxirida.

Commit (sarlavha va tana):

bash
git commit -m "chore: knip — 3 ta ishlatilmagan tur eksporti; hujjatlar v6" \
  -m "README, AGENTS, TEXNIK-QARZ v6; tekshiruv/ssenariy.md"

Shu commitda 16-qism hujjatlari ham yangilanadi: README (Vite bilan build, dev/preview/analiz, brauzerlar, tekshirish, litsenziya), AGENTS.md (buyruqlar, Vite qoidalari, commitlint) va TEXNIK-QARZ. Bu — vazifalar v6 ning yakuniy qadami.

4. knip yana nimalarni topadi

vazifalar da faqat tur eksportlari chiqdi. Boshqa bo'limlarni ko'rish uchun vaqtincha uchta "xato" qo'shdik: hech kim import qilmaydigan src/eski.ts, ishlatilmaydigan picocolors paketi va taymer.ts da package.json da yo'q ms paketini import qilish:

text
Unused files (1)
src/eski.ts
Unused devDependencies (1)
picocolors  package.json:31:6
Unlisted dependencies (1)
ms  src/taymer.ts:51:16
Unused exports (1)
KUTISH  src/taymer.ts:52:14
Unused exported types (3)
…
Bo'lim Ma'nosi Odatiy davosi
Unused files hech kim import qilmaydigan fayl o'chirish
Unused dependencies / devDependencies package.json da bor, kodda yo'q npm uninstall
Unlisted dependencies kodda bor, package.json da yo'q npm i bilan qo'shish
Unused exports / types eksport tashqarida ishlatilmaydi export ni olish yoki o'chirish

Unlisted eng xavflisi. ms node_modules da bor edi — ESLint uni o'zi bilan olib kelgan (npm buyruqlari: eslint → debug → ms). Kod hozir ishlaydi. Lekin ESLint yangilanib debug dan voz kechsa, ms yo'qoladi va taymer.ts sinadi. pnpm buni darhol to'xtatardi (pnpm), npm esa ruxsat beradi — knip bu bo'shliqni yopadi. Tajribadan keyin hammasini qaytardik.

5. knip.json: kam sozlama — yaxshi sozlama

Mashq loyihasida npm init -y qoldirgan bir tuzoq chiqdi:

text
Configuration hints (1)
index.js    package.json  Package entry file not found

"Paketning kirish fayli topilmadi": npm init -y "main": "index.js" yozadi, bunday fayl esa yo'q. knip shunday maslahatlar (hints) ham beradi. npm pkg delete main — maslahat yo'qoldi.

Ba'zan topilma ataylab: masalan, src/chegirma.ts hali ulanmagan, lekin keyingi hafta ulanadi. Uni hisobotdan chiqarish uchun knip.json:

json
{
  "$schema": "https://unpkg.com/knip@6/schema.json",
  "ignore": ["src/chegirma.ts"]
}

$schema — config fayllar darsidagi muharrir yordamchisi. Biz avval entry va project ham yozgan edik — knip o'zi tuzatdi:

text
Configuration hints (1)
src/index.ts    knip.json  Remove redundant entry pattern

"Ortiqcha entry naqshini olib tashlang": src/index.ts knip'ning sukutdagi kirish nuqtalaridan biri. Qoida: avval sozlamasiz ishga tushiring, faqat haqiqiy muammo bo'lsa sozlang. vazifalar da knip.json umuman yo'q.

Diqqat: ignore — "ko'rmayman" degani, "yaxshi" emas. Har ignore ga sabab yozing (README yoki commit'da) va vaqti-vaqti bilan qayta ko'ring. Aks holda knip.json o'lik kodning yangi omboriga aylanadi.

6. Boshqa vositalar

6.1 depcheck — nega knip yaxshiroq

depcheck (1.4.7) — faqat paketlarni tekshiradi. vazifalar da:

bash
npx depcheck@1.4.7
text
Unused devDependencies
* @commitlint/cli
* @commitlint/config-conventional
* lint-staged

Uchala natija — noto'g'ri. commitlint .husky/commit-msg da, lint-staged — .husky/pre-commit da ishlatiladi (Husky). depcheck husky fayllarini o'qimaydi va ularni "keraksiz" deydi. Kimdir unga ishonib o'chirsa — hook'lar sinadi. knip esa husky va lint-staged plaginlari bilan ularni to'g'ri tanidi. Bu farq — vosita tanlashda o'lchash nega kerakligining yana bir misoli.

6.2 madge — aylanma importlar

Aylanma import (circular dependency) — a.ts b.ts ni, b.ts esa a.ts ni import qiladi. Bu ba'zan undefined qiymatlarga va g'alati xatolarga olib keladi. madge (8.0.0) shunday aylanalarni topadi:

bash
npx madge@8.0.0 --circular --extensions ts src/
text
- Finding files
Processed 21 files (14s) 

✔ No circular dependency found!

vazifalar da aylana yo'q — 21 faylning importlari bir tomonlama oqadi. madge grafni rasm qilib ham chiza oladi (--image, Graphviz dasturi kerak).

6.3 dependency-cruiser va ts-prune

  • dependency-cruiser (18.5.0) — import qoidalarini yozish va tekshirish: "src/ dagi kod tekshiruv/ dan import qilmasin", "UI qatlami ma'lumotlar bazasini to'g'ridan-to'g'ri chaqirmasin". Arxitektura qoidalari uchun — katta loyihalarda (arxitektura darslarida qaytamiz).
  • ts-prune — ishlatilmagan TypeScript eksportlarini topardi. Oxirgi versiyasi 2022-yilda chiqqan; vazifasini bugun knip bajaradi. Eski loyihalarda uchratsangiz — knip'ga almashtirish nomzodi.
Vosita Nima topadi Holati (2026-10)
knip fayllar, eksportlar, turlar, paketlar faol, 6.40.0 (6.41.0 ham chiqdi)
depcheck faqat paketlar 1.4.7 (2025-08), plaginsiz
madge aylanma importlar, graf rasmi 8.0.0 (2024-08)
dependency-cruiser import qoidalari faol, 18.5.0

7. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
ishlatiladigan fayl "Unused files" da kirish nuqtasi noma'lum (maxsus asbob) knip.json da entry
Package entry file not found main dagi fayl yo'q npm pkg delete main yoki to'g'ri yo'l
Remove redundant entry pattern sukutdagi narsa qayta yozilgan knip.json dan o'chiring
export olindi — boshqa fayl sinadi eksport aslida ishlatilardi (dinamik import) tsc -b va testlar bilan tekshiring

Oxirgisi muhim: knip statik tahlil qiladi. import(\./${nom}.ts`)kabi dinamik yo'lni u to'liq ko'ra olmaydi. Har tuzatishdan keyinnpm run check`.

8. Mashqlar

Mashq loyihasi kurs/mashqlar/16/48-knip/: npm init -y, npm pkg set type=module, npm i -E nanoid@6.0.2 picocolors@1.1.1, npm i -D -E knip@6.40.0 typescript@7.0.2. src/index.ts:

ts
// «Bahor» buyurtma raqami va narxi
import { nanoid } from "nanoid";
import { formatPrice } from "./narx.ts";

console.log(`Buyurtma ${nanoid(6)}: ${formatPrice(35000)}`);

src/narx.ts:

ts
export function formatPrice(price: number): string {
  return `${price} so'm`;
}

// Eski narx formati — endi ishlatilmaydi
export function oldPrice(price: number): string {
  return `${price / 1000} ming`;
}

src/chegirma.ts:

ts
// Chegirma hisobi — hali hech qayerga ulanmagan
export const DISCOUNT = 0.1;

1-mashq (oson): hisobotni o'qing

npx knip ni ishga tushiring va to'ldiring:

  • Ishlatilmagan fayl:
  • Ishlatilmagan paket:
  • Ishlatilmagan eksport:
Yechim
text
Unused files (1)
src/chegirma.ts
Unused dependencies (1)
picocolors  package.json:16:6
Unused exports (1)
oldPrice  function  src/narx.ts:6:17
Configuration hints (1)
index.js    package.json  Package entry file not found

Chiqish kodi 1. Oxirgi qator — maslahat: npm init -y qoldirgan "main": "index.js".

2-mashq (o'rta): tozalang

Maslahatni tuzating (main), picocolors ni olib tashlang, oldPrice ni o'chiring. chegirma.ts esa kerak — keyingi hafta ulanadi: uni o'chirmay, hisobotdan chiqaring. npx knip jim bo'lsin, node src/index.ts ishlasin.

Yechim
bash
npm pkg delete main
npm uninstall picocolors

src/narx.ts dan oldPrice va uning izohi o'chiriladi. knip.json — «knip.json» bo'limidagidek (ignore: ["src/chegirma.ts"]). Natija: npx knip — chiqish yo'q, chiqish kodi 0; node src/index.ts → Buyurtma <tasodifiy 6 belgi>: 35000 so'm.

3-mashq (o'rta): eksportmi yoki o'chirishmi?

Har holatda qaror qabul qiling va sababini yozing:

  1. formatDate — utils.ts dan eksport qilinadi, faqat shu faylning ichida ishlatiladi.
  2. LegacyUser turi — hech qayerda ishlatilmaydi, 2024-yilgi API uchun yozilgan.
  3. createTestOrder — faqat tekshiruv/ dagi testlar ishlatadi, lekin knip uni "unused" demoqda.
Yechim
  1. export ni olib tashlash — funksiya kerak, faqat tashqariga emas (YangiVazifa kabi).
  2. O'chirish — hech kim ishlatmaydi (ApiKlient kabi). Git tarixida baribir qoladi.
  3. Avval tekshirish: knip test fayllarini ko'ryaptimi? Odatda node:test, Vitest plaginlari ularni o'zi topadi. Ko'rmasa — knip.json dagi entry ga test naqshini qo'shish. Eksport ishlatiladi, demak, o'chirish emas, sozlash kerak.

4-mashq (qiyin): Vazifalar qadami

kurs/vazifalar da branch chore/knip: npm i -D knip@6.40.0, npx knip. Uchta topilmani tahlil qiling va «Uchta topilma — ikki xil qaror» bo'limidagidek tuzating. "knip": "knip" skriptini qo'shing. Keyin npx depcheck@1.4.7 ni ham ishga tushiring — u nima deydi va nega unga ishonmaslik kerak?

Yechim

Tuzatishdan keyin npm run knip — jim, chiqish kodi 0; npm run check — toza. depcheck commitlint va lint-staged'ni "unused" deydi — noto'g'ri: ular husky hook'larida ishlatiladi. O'chirsangiz, keyingi git commit da .husky/pre-commit lint-staged ni topa olmaydi. Diff: 8 fayl (lock va hujjatlar bilan).

9. Real ishda

  • Katta loyihalarda knip birinchi ishga tushirilganda yuzlab topilma chiqaradi. Hammasini bir PR'da tuzatmaydilar: avval paketlar, keyin fayllar, keyin eksportlar — kichik qadamlar bilan.
  • Kutubxona tanlash va yangilash (Paket tanlash, Bog'liqliklarni yangilash) bilan birga: ishlatilmagan paket — yangilanishi ham, xavfsizlik tekshiruvi ham shart bo'lmagan paket.
  • Refaktoringdan keyin knip — "nima qolib ketdi?" savoliga tez javob (Code smell va refactoring).
  • Intervyu: "O'lik kodni qanday topasiz?", "unlisted dependency nima va nega xavfli?", "knip va depcheck farqi?".

10. 16-qism yakuni: vazifalar v5 → v6

knip — qismning oxirgi qadami. Endi orqaga qaraymiz: 15-qism oxiridagi vazifalar (v5) va hozirgisi (v6). Raqamlar — haqiqiy o'lchov (Node 24.21.0, Chrome 154, Lighthouse 13.5.0 mobil):

v5 (15-qism oxiri) v6 (hozir)
Build tsc + nusxalash skripti tsc -b && vite build (Vite 8.3.3)
Brauzer yuklaydigan JS + CSS 85.8 KB 38.1 KB
Xuddi shu, gzip 32.0 KB 14.3 KB
Fayllar (so'rovlar) 20 4
Lighthouse FCP / LCP 1.3 s / 1.8 s 1.1 s / 1.5 s
v5 (15-qism oxiri) v6 (hozir)
Testlar 143 146
Lint recommended + 3 ta async qoida recommendedTypeChecked
Tur tekshiruvi bitta tsconfig, faqat src/ app + node, tsc -b (Node kodi ham)
Commit himoyasi yo'q commitlint, husky, lint-staged
node_modules 86 MB 168 MB

Ikki narsa o'zgarmadi, va bu ham natija. Birinchisi — sahifa xulqi: CSP bir harf ham o'zgarmadi, 159 ta brauzer tekshiruvi har qadamda o'tdi, Lighthouse balli — 100. Ikkinchisi — qoida: har asbob o'lchov bilan kirdi yoki chiqdi. Zod (bundle'ga +23.7 KB gzip) va alias (Node testlarini buzdi) kanonga kirmadi, knip esa eski kodni topdi. Narxi ham ochiq: node_modules ikki baravar o'sdi.

17-qism nimaga tayanadi. React loyihasi aynan shu zanjirda yashaydi:

  • Vite — React shabloni create-vite dan, vite.config.ts ga bitta @vitejs/plugin-react qo'shiladi (Vite II da o'qigan config).
  • tsconfig app/node — tsconfig.app.json ga jsx: "react-jsx" qo'shiladi, fayllar .tsx bo'ladi (tsconfig app va node).
  • ESLint — react-hooks va react-refresh plaginlari (ESLint II da sozlamasini o'qigansiz).
  • npm run check, husky, commitlint — har React commiti ham shu himoyadan o'tadi.
  • Testlar hozircha node:test da qoladi; Vitest — 22-qismda.

vazifalar dagi qo'lda yozilgan render.ts — 17-qismning boshlang'ich nuqtasi: uni React komponentlari bilan solishtiramiz.

Xulosa

  • knip kirish nuqtalaridan import grafini quradi va undan tashqarida qolganni topadi: fayllar, eksportlar, turlar, paketlar.
  • Plaginlar (Vite, ESLint, commitlint, husky, lint-staged, node:test) — sozlamasiz to'g'ri natija; depcheck esa husky'dagi paketlarni noto'g'ri "unused" dedi.
  • vazifalar: 3 ta tur eksporti — YangiVazifa, Amal (export olindi), ApiKlient (o'chirildi); build o'zgarmadi.
  • "Unlisted" — eng xavfli: boshqa paket olib kelgan bog'liqlikka tayanish.
  • knip.json — minimal; knip o'zi ortiqcha sozlamani aytadi. CI'da emas, vaqti-vaqti bilan.
  • 16-qism yakuni: vazifalar v6 — Vite, typed lint, commitlint, husky, tsconfig app/node, ildiz fayllar va toza kod; JS + CSS 85.8 → 38.1 KB (gzip 32.0 → 14.3 KB), 20 → 4 fayl, 146 test.

Keyingi dars: React nima va nega — 17-qism boshlanadi: vazifalar dagi qo'lda yozilgan render'ni deklarativ UI bilan solishtiramiz; bu qismda o'qigan React config fayllari endi ishga tushadi.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
knip: ishlatilmagan fayl, eksport va bog'liqliklarni topish — IlmHamroh