IlmHamroh
JavaScript Full-stack/16-qism. Frontend asboblari: npm, bundlerlar, config6/48-dars22 daqiqa
Mundarija (29)

npm scripts chuqur: pre/post skriptlar, argumentlar va Windows tuzoqlari

Qisqacha: package.json dagi scripts — loyihaning buyruq paneli: npm run nom buyruqni node_modules/.bin PATH'ga qo'shilgan holda ishga tushiradi. pre<nom> va post<nom> skriptlari o'zi oldin va keyin bajariladi, skriptga argument esa -- dan keyin beriladi. Windows'da skriptlar cmd da ishlaydi, shuning uchun rm -rf, NODE_ENV=… va bittalik qo'shtirnoq u yerda buziladi — node -e, cross-env yoki --env-file bilan yeching.

Bu darsda

  • npm run skriptni qanday ishga tushirishini va nega prettier terminalda topilmasa ham skriptda topilishini tushunasiz.
  • pre/post skriptlar tartibini va --ignore-scripts ni bilasiz.
  • Skriptga argumentni -- bilan to'g'ri uzatasiz va npm_lifecycle_event kabi o'zgaruvchilarni o'qiysiz.
  • Ketma-ket (&&, run-s) va parallel (run-p, concurrently) ishga tushirishni farqlaysiz.
  • Windows'da buziladigan skriptlarni taniysiz va vazifalar ga npm run check qo'shasiz.

Oldin bilishingiz kerak: package.json II: bog'liqlik turlari, npm'ga birinchi qadam, Exit code va buyruqlarni zanjirlash.

1. Nega bu kerak?

vazifalar ni push qilishdan oldin Sardor to'rtta buyruq yozadi: npm run format:check, npm run lint, npm run tip, npm test. Bir kuni u shoshib npm test ni yozdi-yu, lint ni unutdi. CI qizarib ketdi. Jasur aka so'radi: "Nega GitHub'da tekshiradigan narsani kompyuteringda bitta buyruq bilan tekshirmaysan?"

Ikkinchi voqea. Malika Windows'da «Bahor» menyu loyihasini ochdi. Sardor macOS'da yozgan "tozala": "rm -rf dist" skripti uning kompyuterida xato berdi.

npm'ga birinchi qadam darsida scripts ga nom berib, npm run nom qilishni o'rgangansiz. Bugun uning ichini ochamiz: npm skriptni qanday ishga tushiradi, unga nima beradi va qayerda buziladi.

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

2. npm run ichida nima bo'ladi

2.1 Mashq loyihasi

kurs/mashqlar/16/06-skriptlar/ da npm init -y, npm pkg set type=module. menyu.js — dist/menyu.txt ga menyu yozadi:

js
// menyu.js — «Bahor» menyusini dist/menyu.txt ga yozadi
import { mkdirSync, writeFileSync } from "node:fs";

const menu = ["Osh — 35000", "Lag'mon — 28000", "Manti — 30000"];
mkdirSync("dist", { recursive: true });
writeFileSync("dist/menyu.txt", menu.join("\n") + "\n");
console.log(`dist/menyu.txt: ${menu.length} ta taom`);

Skriptlarni npm pkg set bilan qo'shamiz (uning chiqishi yo'q — jim tugaydi):

bash
npm pkg set scripts.prebuild="echo 1-prebuild" \
  scripts.build="node menyu.js" scripts.postbuild="echo 3-postbuild"

npm run nom berilmasa — ro'yxatni chiqaradi:

bash
npm run
text
Lifecycle scripts included in 06-skriptlar@1.0.0:
  test
    echo "Error: no test specified" && exit 1
available via `npm run`:
  prebuild
    echo 1-prebuild
  build
    node menyu.js
  postbuild
    echo 3-postbuild

Ikki guruh bor. Lifecycle (hayot sikli) skriptlari — test, start, stop, restart: ular uchun run shart emas, npm test yetadi. Qolganlari faqat npm run nom bilan ishlaydi. Begona loyihani ochganda birinchi buyruq shu — "bu yerda qanday buyruqlar bor?".

2.2 Skript qayerda ishlaydi

npm run build bajarilganda npm uchta ish qiladi:

  1. Joriy papkadan yuqoriga qarab package.json ni topadi va ishchi papkani shu papka qiladi. src/ ichida turib ham npm run build qilsangiz, skript ildizda ishlaydi.
  2. PATH'ning boshiga node_modules/.bin ni qo'shadi.
  3. Skript matnini shellga (buyruq qatori dasturiga) beradi: Windows'da — cmd.exe, macOS va Linux'da — sh.

Ikkinchi band — ko'p savollarning javobi. rimraf paketini (pastda) o'rnatgandan keyin terminalda:

bash
rimraf --version
text
/usr/bin/bash: line 1: rimraf: command not found

Terminal rimraf ni tanimaydi: u node_modules/.bin ga qaramaydi. Skript ichida esa PATH'ning birinchi papkasi:

text
…\kurs\mashqlar\16\06-skriptlar\node_modules\.bin

Shuning uchun scripts da npx yozmasdan prettier --check . deyish yetadi. Terminalda esa npx rimraf --version — u ham shu papkaga qaraydi (npx darsida chuqur).

2.3 Chiqish kodi

Skriptning chiqish kodi — npm run ning chiqish kodi. Exit code darsida o'rganganingizdek, 0 — muvaffaqiyat, boshqasi — xato. CI ham, && zanjiri ham aynan shunga qaraydi.

Tekshirib ko'ring: Bobur vazifalar/assets/js/ papkasida turib npm run lint yozdi. ESLint qaysi papkani tekshiradi?

Javob

Butun loyihani. npm package.json ni yuqoridan topib, skriptni ildiz papkada ishga tushiradi — eslint . dagi . ildizni bildiradi. Faqat assets/js/ kerak bo'lsa, argument bering («Argument uzatish» bo'limi).

3. pre va post skriptlar

3.1 Tartib

build uchun npm avval prebuild, keyin build, oxirida postbuild ni qidiradi:

bash
npm run build
text

> 06-skriptlar@1.0.0 prebuild
> echo 1-prebuild

1-prebuild

> 06-skriptlar@1.0.0 build
> node menyu.js

dist/menyu.txt: 3 ta taom

> 06-skriptlar@1.0.0 postbuild
> echo 3-postbuild

3-postbuild

Har skript oldidan npm ikki qator yozadi: > paket@versiya nom va > buyruq. Bu ham ma'lumot: qaysi skript, qanday matn bilan ishga tushdi.

flowchart LR
  A["npm run build"] --> B["prebuild"]
  B -- "0" --> C["build"]
  C -- "0" --> D["postbuild"]
  B -- "0 emas" --> X["to'xtaydi"]
  C -- "0 emas" --> X

Sxemadagi qoida: pre xato bilan tugasa, asosiy skript ishlamaydi. Sinov — prebuild ni node -e "process.exit(1)" qildik:

bash
npm run build
text

> 06-skriptlar@1.0.0 prebuild
> node -e "process.exit(1)"

Faqat prebuild ishladi, build ga navbat kelmadi, chiqish kodi 1.

pre/post ning kamchiligi — ular yashirin. build ni o'qigan odam prebuild borligini bilmasligi mumkin. Shuning uchun ko'p jamoa ularni kam ishlatadi va zanjirni ochiq yozadi: "build": "node tozala.js && node menyu.js". vazifalar da ham shunday bo'ladi: v5 dagi prebuild (dist'ni tozalash) Vite kelganda olib tashlanadi — Vite dist/ ni o'zi tozalaydi (Bundler nima).

3.2 Ovozni pasaytirish va o'chirish

--silent (-s) npm'ning > qatorlarini yashiradi — faqat skriptlarning o'z chiqishi qoladi:

bash
npm run build --silent
text
1-prebuild
dist/menyu.txt: 3 ta taom
3-postbuild

--ignore-scripts esa pre va post ni o'tkazib yuboradi:

bash
npm run build --ignore-scripts
text

> 06-skriptlar@1.0.0 build
> node menyu.js

dist/menyu.txt: 3 ta taom

Bu bayroq aslida xavfsizlik uchun yaratilgan: npm install --ignore-scripts paketlarning o'rnatish skriptlarini (postinstall) bloklaydi. Bu haqda Ta'minot zanjiri xavfsizligi darsida.

3.3 Yo'q skript va --if-present

bash
npm run lint
text
npm error Missing script: "lint"
npm error
npm error Did you mean this?
npm error   npm link # Symlink a package folder
npm error
npm error To see a list of scripts, run:
npm error   npm run
npm error A complete log of this run can be found in: …\npm-cache\_logs\2026-10-10T14_30_00_445Z-debug-0.log

"lint skripti yo'q. Shuni nazarda tutdingizmi: npm link?" npm o'xshash buyruqni taklif qildi, lekin bu umuman boshqa narsa. npm run lint --if-present esa skript yo'q bo'lsa jim tugaydi (chiqish kodi 0). Ko'p loyihalarni bir xil CI bilan tekshirganda qulay.

Tekshirib ko'ring: "pretest": "npm run lint" va "test": "node --test". npm test da lint xato topsa, testlar ishlaydimi?

Javob

Yo'q. pretest 1 bilan tugaydi va npm test ni boshlamaydi. npm test ham 1 bilan tugaydi. Lekin npm test --ignore-scripts lint'ni chetlab o'tadi — yashirin bog'lanishning yana bir xavfi.

4. Argument uzatish va skript o'zgaruvchilari

4.1 -- belgisi

info.js — skriptga nima kelayotganini ko'rsatadi:

js
// info.js — npm skriptga qanday ma'lumot beradi?
const env = process.env;
console.log("hodisa:", env.npm_lifecycle_event);
console.log("paket:", env.npm_package_name, env.npm_package_version);
console.log("argumentlar:", process.argv.slice(2));

"info": "node info.js". Argument bilan, -- orqali:

bash
npm run info -- --narx 35000 osh
text

> 06-skriptlar@1.0.0 info
> node info.js --narx 35000 osh

hodisa: info
paket: 06-skriptlar 1.0.0
argumentlar: [ '--narx', '35000', 'osh' ]

-- — "bundan keyingisi npm uchun emas, skript uchun". npm uni skript matni oxiriga qo'shdi — ikkinchi > qatorida ko'rinib turibdi. Endi -- siz:

bash
npm run info --narx 35000 osh
text
npm warn "35000" is being parsed as a normal command line argument.
npm warn Unknown cli config "--narx". This will stop working in the next major version of npm.

> 06-skriptlar@1.0.0 info
> node info.js 35000 osh

hodisa: info
paket: 06-skriptlar 1.0.0
argumentlar: [ '35000', 'osh' ]

"--narx — noma'lum npm sozlamasi. Keyingi asosiy versiyada bu ishlamay qoladi". npm -- bilan boshlangan so'zni o'ziga oldi va tashladi. osh kabi oddiy so'zlar -- siz ham o'tadi, lekin bayroqlar — yo'q. Qoida: skriptga bayroq berilsa, doim -- qo'ying.

vazifalar da bu har kuni kerak: 143 ta testdan faqat bittasini yuritish.

bash
npm test -- --test-name-pattern="paketniTekshir"
text

> test
> node --test --test-name-pattern=paketniTekshir

…
▶ paketniTekshir
✔ paketniTekshir (9.2855ms)
…
ℹ tests 16
ℹ suites 1
ℹ pass 16
ℹ fail 0

(Fayl qatorlari qisqartirildi.) 16 ta test — paketniTekshir guruhi. -- siz esa npm bayroqni yutadi va 143 ta test ishga tushadi — xuddi yuqoridagi --narx kabi.

4.2 npm beradigan o'zgaruvchilar

npm skriptga o'nlab muhit o'zgaruvchisi beradi. Ulardan foydalilari:

O'zgaruvchi Qiymat (info da)
npm_lifecycle_event ishlayotgan skript nomi: info
npm_lifecycle_script skript matni: node info.js
npm_package_name 06-skriptlar
npm_package_version 1.0.0
O'zgaruvchi Qiymat (info da)
npm_package_json package.json ning to'liq yo'li
npm_command run
npm_config_* npm sozlamalari
INIT_CWD npm run yozilgan papka

npm_lifecycle_event bilan bitta fayl turli skriptlarda turlicha ishlashi mumkin. INIT_CWD esa «Skript qayerda ishlaydi» bo'limidagi "ildizda ishlaydi" qoidasining yechimi: foydalanuvchi qayerda turganini aytadi.

Tuzoq: eski maqolalarda npm_package_config_port, npm_package_scripts_build kabi o'zgaruvchilar uchraydi. npm 7 dan beri package.json ning hamma maydoni emas, faqat name, version va bir nechtasi beriladi. Biz Node 24 da npm_ bilan boshlangan o'zgaruvchilarni sanadik — npm_package_ lardan faqat uchtasi bor edi: json, name, version. Boshqa maydon kerak bo'lsa, npm_package_json dagi faylni o'qing.

Tekshirib ko'ring: "salom": "node info.js" va npm run salom -- -s. Skript -s ni oladimi yoki npm uni --silent deb tushunadimi?

Javob

Skript oladi: argumentlar: [ '-s' ]. -- dan keyin npm hech narsani o'zi uchun o'qimaydi. npm run salom -s desangiz esa npm jim rejimga o'tadi va skriptga hech narsa bermaydi.

5. Ketma-ket va parallel

5.1 && — ketma-ket

pishir.js — taomni "pishiradi": nomni yozadi va soniya kutadi.

js
// pishir.js — taomni "pishiradi": node pishir.js <nom> <soniya>
const [name, seconds] = process.argv.slice(2);
console.log(`${name}: boshlandi`);
setTimeout(() => console.log(`${name}: tayyor`), seconds * 1000);

"osh": "node pishir.js osh 2", "choy": "node pishir.js choy 1" va "ketma": "npm run osh && npm run choy":

bash
npm run ketma
text

> 06-skriptlar@1.0.0 ketma
> npm run osh && npm run choy


> 06-skriptlar@1.0.0 osh
> node pishir.js osh 2

osh: boshlandi
osh: tayyor

> 06-skriptlar@1.0.0 choy
> node pishir.js choy 1

choy: boshlandi
choy: tayyor

Choy faqat osh tayyor bo'lgach boshlandi. && — "oldingisi 0 bilan tugasa, keyingisi". Bu cmd da ham, sh da ham bir xil ishlaydi — shuning uchun tekshiruv zanjirlari uchun eng ishonchli yo'l. ; esa sh da "baribir davom et" degani, cmd da esa umuman ajratuvchi emas — skriptlarda ishlatmang.

5.2 Parallel: run-p va concurrently

Ba'zan ikki ish bir vaqtda kerak: masalan, dev server va tur tekshiruvi. sh da & buyruqni fonda ishga tushiradi, cmd da esa & — oddiy ketma-ketlik. Shuning uchun parallel ishga maxsus paketlar ishlatiladi:

bash
npm i -D -E concurrently@10.0.6 npm-run-all2@9.0.3
text

added 30 packages, and audited 48 packages in 9s

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

found 0 vulnerabilities

npm-run-all2 ikki buyruq beradi: run-s (ketma-ket) va run-p (parallel). "rp": "run-p osh choy":

bash
npm run rp
text

> 06-skriptlar@1.0.0 rp
> run-p osh choy


> 06-skriptlar@1.0.0 osh
> node pishir.js osh 2


> 06-skriptlar@1.0.0 choy
> node pishir.js choy 1

choy: boshlandi
osh: boshlandi
choy: tayyor
osh: tayyor

Ikkalasi birga boshlandi, choy (1 soniya) oshdan (2 soniya) oldin tayyor. Bizda ketma 5.2 soniya, rp 3.4 soniya oldi (bir o'lchov; har birida npm'ning ishga tushishi ham bor).

concurrently har qatorga skript nomini yozadi — ko'p chiqishda kim nima deganini ajratish oson. "parallel": "concurrently \"npm:osh\" \"npm:choy\"" (npm: — "shu nomli npm skripti"):

bash
npm run parallel
text

> 06-skriptlar@1.0.0 parallel
> concurrently "npm:osh" "npm:choy"

[osh] 
[osh] > 06-skriptlar@1.0.0 osh
[osh] > node pishir.js osh 2
[osh] 
[choy] 
[choy] > 06-skriptlar@1.0.0 choy
[choy] > node pishir.js choy 1
[choy] 
[osh] osh: boshlandi
[choy] choy: boshlandi
[choy] choy: tayyor
[choy] npm run choy exited with code 0
[osh] osh: tayyor
[osh] npm run osh exited with code 0

Terminalda prefikslar rangli. Qachon nima:

Vazifa Yo'l
tekshiruvlar zanjiri (birinchi xatoda to'xta) &&
ko'p skript, ketma-ket, qisqa yozuv run-s lint tip test
dev server + kuzatuvchi run-p yoki concurrently

npm-run-all (2 siz) — eski paket, oxirgi versiyasi 4.1.5 2018-yilda chiqqan; uning davomchisi — npm-run-all2. Eski loyihalarda birinchisini uchratsangiz, almashtirish oson: buyruqlar bir xil.

Tekshirib ko'ring: "check": "run-p lint test". Lint xato topdi. Testlar ishlaydimi?

Javob

Ha, ular allaqachon parallel boshlangan. run-p biri yiqilsa, qolganlarini to'xtatadi va 1 bilan tugaydi, lekin "lint o'tmasa test ham kerak emas" degan tejamkorlik yo'q. Tekshiruv zanjirida && aniqroq: birinchi xatoda to'xtaydi va xato chiqishi aralashmaydi.

6. Windows tuzoqlari

6.1 Uch klassik xato

npm Windows'da skriptni cmd.exe ga beradi. Sardor macOS'da yozgan uchta skript:

json
{
  "scripts": {
    "tozala": "rm -rf dist",
    "prod": "NODE_ENV=production node muhit.js",
    "salom": "echo 'Salom, Bahor'"
  }
}

Malika'ning kompyuterida (PowerShell'dan):

bash
npm run tozala
text

> 06-skriptlar@1.0.0 tozala
> rm -rf dist

'rm' is not recognized as an internal or external command,
operable program or batch file.

cmd da rm yo'q (uning o'z buyrug'i — rmdir /s /q). Git Bash'dan ishga tushirsangiz, rm topilishi mumkin — Git o'z buyruqlarini PATH'ga qo'shgan bo'lsa. Shuning uchun xato "menda ishlaydi" ko'rinishida yashirinadi.

bash
npm run prod
text

> 06-skriptlar@1.0.0 prod
> NODE_ENV=production node muhit.js

'NODE_ENV' is not recognized as an internal or external command,
operable program or batch file.

NOM=qiymat buyruq — sh sintaksisi: "shu buyruq uchun o'zgaruvchi ber". cmd esa NODE_ENV ni buyruq nomi deb o'yladi.

bash
npm run salom
text

> 06-skriptlar@1.0.0 salom
> echo 'Salom, Bahor'

'Salom, Bahor'

Xato yo'q, lekin qo'shtirnoqlar ham chiqdi: cmd bittalik qo'shtirnoqni tanimaydi. echo "Salom, Bahor" ham cmd da qo'shtirnoq bilan chiqadi — cmd ning echo si matnni boricha yozadi.

6.2 Yechimlar

Eng yaxshi yechim — skriptda shell buyruqlari o'rniga Node. Node hamma tizimda bir xil:

Muammo Node bilan Paket bilan
rm -rf dist node -e "fs.rmSync('dist', { recursive: true, force: true })" rimraf dist
NODE_ENV=production … node --env-file=.env.production … cross-env NODE_ENV=production …
echo '…' node -e "console.log('…')" —

node -e da fs ni import qilish shart emas: Node -e rejimida o'z modullarini nomi bilan beradi. vazifalar ning v5 dagi prebuild skripti aynan shunday yozilgan — u 15-qismdan beri Windows'da ham, CI'dagi Linux'da ham ishlaydi.

--env-file — Node 20.6 dan bor bayroq: fayldagi NOM=qiymat qatorlarini muhit o'zgaruvchisiga aylantiradi. U .env darsidagi dotenv-cli paketining o'rnini bosadi. Fayl yo'q bo'lsa — node: .env.local: not found va chiqish kodi 9. "Bo'lmasa ham mayli" degan holat uchun --env-file-if-exists: .env.local not found. Continuing without it. deb davom etadi.

Paketlar ham ishlaydi:

bash
npm i -D -E cross-env@10.1.0 rimraf@6.1.3
text

added 17 packages, and audited 18 packages in 4s

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

found 0 vulnerabilities
bash
npm run prod
text

> 06-skriptlar@1.0.0 prod
> cross-env NODE_ENV=production node muhit.js

NODE_ENV: production

muhit.js — process.env.NODE_ENV ni chiqaradigan bir qatorli fayl. Lekin narxiga qarang: ikkita kichik ish uchun 17 ta paket. Node bilan yechish mumkin bo'lsa — paket qo'shmang (Paket tanlash darsi shu savolga bag'ishlangan).

npm'da script-shell sozlamasi ham bor: masalan, Windows'da skriptlarni Git Bash bilan yuritish. Lekin u har kompyuterda alohida sozlanadi. Jamoadoshingizda bo'lmasa, skript baribir buziladi — shuning uchun skriptning o'zi hamma joyda ishlashi kerak.

6.3 node --run

Node 22 dan node --run nom ham package.json skriptini ishga tushiradi — npm'siz va tezroq:

bash
node --run build
text
dist/menyu.txt: 3 ta taom

Farqiga qarang: 1-prebuild va 3-postbuild chiqmadi. node --run pre/post ni ishga tushirmaydi va npm_* o'zgaruvchilarini umuman bermaydi — faqat NODE_RUN_SCRIPT_NAME va NODE_RUN_PACKAGE_JSON_PATH. Tez tekshiruvlar uchun qulay, lekin pre/post ga tayangan loyihada xulq o'zgaradi.

Tekshirib ko'ring: CI (GitHub Actions) Linux'da ishlaydi. Sardor "tozala": "rm -rf dist" ni CI'da sinab, "ishlayapti" dedi. Nega bu yetarli emas?

Javob

CI sh da ishlaydi, rm u yerda bor. Windows'dagi jamoadosh esa cmd da 'rm' is not recognized oladi. Skript loyihaning hamma ishtirokchisi uchun yoziladi — node -e yoki rimraf hamma joyda ishlaydi.

7. Ko'p uchraydigan xatolar

Xabar Sabab Davosi
Missing script: "lint" skript yo'q yoki nomi xato npm run bilan ro'yxat
Unknown cli config "--…" bayroq -- siz berildi npm run nom -- --bayroq
'rm' is not recognized cmd da Unix buyrug'i node -e, rimraf
'NODE_ENV' is not recognized NOM=qiymat cmd da --env-file, cross-env
Belgi Sabab Davosi
asosiy skript ishlamadi pre… xato bilan tugadi pre… ni tuzating
prettier: command not found terminalda .bin faqat skriptda PATH'da npx prettier
node --run da pre ishlamadi node --run pre/post ni bilmaydi npm run
node: .env.local: not found --env-file fayli yo'q --env-file-if-exists

8. Mashqlar

Mashqlar kurs/mashqlar/16/06-skriptlar/ da.

1-mashq (oson): Tartibni ayting

package.json da: "prebuild": "echo A", "build": "echo B", "postbuild": "echo C", "pretest": "echo D", "test": "echo E". Har buyruq qaysi harflarni qaysi tartibda chiqaradi?

  • npm run build --silent:
  • npm test --silent:
  • npm run build --ignore-scripts --silent:
  • node --run build:
Yechim

pre → asosiy → post. --ignore-scripts pre/post ni o'tkazadi, node --run ularni umuman bilmaydi. test — lifecycle skript, shuning uchun npm test da ham pretest ishlaydi. Har harf alohida qatorda chiqadi.

2-mashq (o'rta): Skriptlarni hamma tizimga moslang

«Uch klassik xato» bo'limidagi uchta skriptni (tozala, prod, salom) paket o'rnatmasdan shunday qayta yozingki, ular cmd da ham, sh da ham bir xil ishlasin. prod uchun .env.production fayli yarating. menyu.js va muhit.js — darsdagidek.

Yordam: «Yechimlar» bo'limidagi jadvalning "Node bilan" ustuni. JSON ichida " ni \" deb yozing.

Yechim

Uch skriptni npm pkg set bilan yozamiz (Git Bash'da; qator oxiridagi \ — buyruq keyingi qatorda davom etadi):

bash
npm pkg set scripts.prod="node --env-file=.env.production muhit.js"
npm pkg set scripts.salom="node -e \"console.log('Salom, Bahor')\""
npm pkg set scripts.tozala="node -e \"fs.rmSync('dist', \
{ recursive: true, force: true })\""
npm pkg get scripts
text
{
  "tozala": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\"",
  "build": "node menyu.js",
  "prod": "node --env-file=.env.production muhit.js",
  "salom": "node -e \"console.log('Salom, Bahor')\""
}

Faylda ichki qo'shtirnoqlar \" bo'lib saqlanadi — JSON qatori ichida qo'shtirnoq shunday yoziladi.

.env.production — bitta qator: NODE_ENV=production. Windows cmd da sinov:

bash
npm run prod
npm run salom
text

> platforma@1.0.0 prod
> node --env-file=.env.production muhit.js

NODE_ENV: production

> platforma@1.0.0 salom
> node -e "console.log('Salom, Bahor')"

Salom, Bahor

Endi qo'shtirnoqsiz. Bittalik qo'shtirnoq bu yerda xavfsiz: u "…" ichida turibdi va uni cmd emas, Node o'qiydi. npm run build, keyin npm run tozala — dist/ o'chadi, xato yo'q.

3-mashq (qiyin): Skript tekshiruvchi

tekshiruvchi/ da skriptlar.mjs yozing: findUnixOnly(scripts) — scripts obyektini oladi va [{ name, hint }] qaytaradi (nom bo'yicha tartiblangan). Topsin: buyruq boshidagi rm, cp, mv; NOM=qiymat; bittalik qo'shtirnoq. "…" ichidagi matnni tekshirmasin — node -e "…" xavfsiz. tekshir.mjs — node tekshir.mjs <papka>, muammo bo'lsa chiqish kodi 1. skriptlar.test.mjs — kamida 2 test.

Ishoralar: replace(/"[^"]*"/g, '""') — qo'shtirnoq ichini bo'shatadi (RegExp asoslari). Buyruq boshi — qator boshi yoki && dan keyin.

Yechim

skriptlar.mjs:

js
// skriptlar.mjs — Windows cmd da ishlamaydigan skriptlarni topadi

// Har qoida: naqsh va o'zbekcha maslahat
const RULES = [
  {
    pattern: /(^|&&\s*|;\s*)rm\s/,
    hint: "rm — rimraf yoki node -e fs.rmSync",
  },
  {
    pattern: /(^|&&\s*|;\s*)(cp|mv)\s/,
    hint: "cp/mv — node -e fs.cpSync yoki fs.renameSync",
  },
  {
    pattern: /(^|&&\s*|;\s*)[A-Z_]+=\S*\s/,
    hint: "NOM=qiymat — cross-env yoki node --env-file",
  },
  {
    pattern: /'[^']*'/,
    hint: "bittalik qo'shtirnoq — cmd uni tushunmaydi",
  },
];

// scripts obyekti → [{ name, hint }] (nom bo'yicha tartiblangan).
// "..." ichidagi matn (masalan node -e "...") tekshirilmaydi
export function findUnixOnly(scripts) {
  const problems = [];
  for (const name of Object.keys(scripts).sort()) {
    const outside = scripts[name].replace(/"[^"]*"/g, '""');
    for (const rule of RULES) {
      if (rule.pattern.test(outside)) {
        problems.push({ name, hint: rule.hint });
      }
    }
  }
  return problems;
}

const found = findUnixOnly({
  tozala: "rm -rf dist",
  build: "node menyu.js",
  prebuild: "node -e \"fs.rmSync('dist', { recursive: true })\"",
});
console.log(found.map((p) => p.name)); // [ 'tozala' ]

Oxirgi uch qator — sinash uchun (faylda shart emas). prebuild ichida ham rm so'zi bor (rmSync), lekin u qo'shtirnoq ichida — tekshirilmadi.

tekshir.mjs:

js
// tekshir.mjs — ishlatish: node tekshir.mjs [papka]
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { findUnixOnly } from "./skriptlar.mjs";

const dir = process.argv[2] ?? ".";
const pkgText = readFileSync(join(dir, "package.json"), "utf8");
const { scripts = {} } = JSON.parse(pkgText);
const problems = findUnixOnly(scripts);

for (const { name, hint } of problems) {
  console.log(`✖ ${name}: ${hint}`);
}
if (problems.length === 0) {
  console.log("✔ hamma skript Windows'da ham ishlaydi");
} else {
  process.exitCode = 1;
}

skriptlar.test.mjs:

js
// skriptlar.test.mjs — node --test skriptlar.test.mjs
import { test } from "node:test";
import assert from "node:assert/strict";
import { findUnixOnly } from "./skriptlar.mjs";

test("Windows'da ishlamaydiganlar topiladi", () => {
  const scripts = {
    tozala: "rm -rf dist",
    prod: "NODE_ENV=production node muhit.js",
    nusxa: "npm run build && cp menyu.txt dist/",
    salom: "echo 'Salom'",
  };
  const problems = findUnixOnly(scripts);
  assert.deepEqual(
    problems.map((p) => p.name),
    ["nusxa", "prod", "salom", "tozala"],
  );
  assert.match(problems[3].hint, /rimraf/);
});

test("xavfsiz skriptlar tegilmaydi", () => {
  const scripts = {
    tozala: "rimraf dist",
    prod: "cross-env NODE_ENV=production node muhit.js",
    test: 'node --test --test-name-pattern="osh"',
    format: "prettier --write .",
    prebuild:
      "node -e \"fs.rmSync('dist', { recursive: true })\"",
  };
  assert.deepEqual(findUnixOnly(scripts), []);
});
text
ℹ tests 2
ℹ pass 2
ℹ fail 0

2-mashqdagi eski (oldin/) skriptlarda:

bash
node tekshir.mjs ../platforma/oldin
text
✖ prod: NOM=qiymat — cross-env yoki node --env-file
✖ salom: bittalik qo'shtirnoq — cmd uni tushunmaydi
✖ tozala: rm — rimraf yoki node -e fs.rmSync

Tuzatilgan (keyin/) da — ✔ hamma skript Windows'da ham ishlaydi, chiqish kodi 0.

4-mashq: Vazifalar qadami — npm run check

«Nega bu kerak?» bo'limidagi muammoni yopamiz: push'dan oldingi to'rt tekshiruv — bitta buyruq, lokalda ham, CI'da ham.

  • Branch: chore/check-skripti
  • Commit: chore: npm run check — format, lint, tip va test bitta buyruqda
  1. package.json ning scripts oxiriga check qo'shing: avval format, keyin lint, tur tekshiruvi va testlar — && bilan.
  2. .github/workflows/pages.yml ning check job'idagi to'rt run qatorini bitta npm run check ga almashtiring.
  3. npm run check ni ishga tushiring, keyin ataylab formatlanmagan fayl qo'shib, zanjir qayerda to'xtashini ko'ring.
Yechim

package.json — scripts oxiriga, qo'lda yoki buyruq bilan:

bash
npm pkg set scripts.check="npm run format:check \
&& npm run lint && npm run tip && npm test"
npm pkg get scripts.check
text
"npm run format:check && npm run lint && npm run tip && npm test"

Tartib bejiz emas: eng tez tekshiruv (Prettier) birinchi, eng uzoq (143 test) oxirida. Xato bo'lsa, tezroq bilasiz.

.github/workflows/pages.yml — check job'i oxiri:

yaml
      - run: npm ci
      # format:check, lint, tip, test — package.json "check" skripti
      # (lokalda ham aynan shu buyruq: npm run check)
      - run: npm run check

Sinov (haqiqiy chiqish, test qatorlari qisqartirilgan). Chiqishda to'rtta > sarlavhani qidiring — format:check, lint, tip, test — ular ketma-ket kelishi va oxirida fail 0 turishi kerak:

bash
npm run check
text

> check
> npm run format:check && npm run lint && npm run tip && npm test


> format:check
> prettier --check .

Checking formatting...
All matched files use Prettier code style!

> lint
> eslint .


> tip
> tsc --noEmit


> test
> node --test

…
ℹ tests 143
ℹ suites 33
ℹ pass 143
ℹ fail 0

> check qatorida versiya yo'q — vazifalar da version maydoni yo'q (pasport darsi). Endi ataylab assets/js/sinov.ts ga const narx =35000 yozdik:

text

> check
> npm run format:check && npm run lint && npm run tip && npm test


> format:check
> prettier --check .

Checking formatting...
[warn] assets/js/sinov.ts
[warn] Code style issues found in the above file. Run Prettier with --write to fix.

Nima bo'ldi? Faqat bitta sarlavha (format:check) chiqdi va Prettier sinov.ts ni ko'rsatdi. Zanjir birinchi halqada to'xtadi, chiqish kodi 1. Lint, tsc va testlar ishlamadi — vaqt tejaldi. sinov.ts ni o'chiring.

Natija: npm test — 143/143, 159 ta brauzer tekshiruvi — 159/159. Ilova xulqi o'zgarmadi.

Commit va PR:

bash
git switch -c chore/check-skripti
npm run check
git add package.json .github/workflows/pages.yml
git commit -m \
"chore: npm run check — format, lint, tip va test bitta buyruqda"
git push -u origin chore/check-skripti
gh pr create --fill
gh pr merge --merge

Commit sarlavhasi — 65 belgi. Diff: 2 fayl, +5 −5. Bundan keyin har push'dan oldin bitta qoida: npm run check.

9. Real ishda

  • Begona loyihada birinchi buyruq — npm run: loyihaning "tugmalar paneli". dev, build, test, lint nomlari deyarli hamma joyda bir xil.
  • CI va lokal bir xil buyruq — yaxshi amaliyot: "CI'da nima tekshirilsa, npm run check ham shuni tekshiradi". Ko'p jamoalar shu nomni (check, verify, ci) ishlatadi.
  • Monorepolarda skriptlar paketlar bo'ylab ishga tushiriladi (npm run test --workspaces) — pnpm darsida ko'ramiz.
  • Intervyu: "npm run build -- --watch dagi -- nima?", "pre/post qanday ishlaydi?", "Nega skript Windows'da ishlamaydi?".

Xulosa

  • npm run nom skriptni loyiha ildizida, node_modules/.bin PATH'da bo'lgan holda, Windows'da cmd da, boshqa tizimlarda sh da ishga tushiradi.
  • pre<nom> → <nom> → post<nom>; pre yiqilsa asosiy ishlamaydi; --ignore-scripts va node --run ularni o'tkazadi.
  • Skriptga bayroq — -- dan keyin; npm_lifecycle_event, npm_package_name, INIT_CWD — foydali o'zgaruvchilar.
  • Ketma-ket — && yoki run-s; parallel — run-p yoki concurrently; & va ; ga tayanmang.
  • Windows tuzoqlari: rm, NOM=qiymat, bittalik qo'shtirnoq — node -e, --env-file, kerak bo'lsa rimraf/cross-env.
  • vazifalar da endi npm run check — lokalda va CI'da bitta tekshiruv.

Keyingi dars: package.json IV: kirish nuqtalari — main, module, exports va types: import "paket" yozganingizda qaysi fayl ochilishini paket qanday belgilaydi.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
npm scripts chuqur: pre/post skriptlar, argumentlar va Windows tuzoqlari — IlmHamroh