WisarWisar
Dasturlash kitobi/15-QISM — Kasbiy konikmalar48 daqiqa

15.4-bob: Monorepo (Turborepo / Nx)

15-QISM — Kasbiy ko'nikmalar · 4-mavzu


1. Kirish va motivatsiya

Tasavvur qiling: sizning loyihangizda frontend (Next.js — web), mobil (React Native), backend (NestJS — API), va ular umumiy kod ishlatadi (TypeScript tiplari, validatsiya sxemalari, UI komponentlari). Bularni qanday tashkil qilasiz? Ikki yondashuv bor: (1) polyrepo — har loyiha alohida repozitoriy (frontend repo, backend repo, mobil repo) — mustaqil, lekin umumiy kodni ulashish qiyin (har repoda nusxa yoki npm paket); (2) monorepobarcha loyiha bir repozitoriyda (frontend, backend, mobil, umumiy paketlar — bir joyda). Monorepo zamonaviy katta loyihalarda juda keng (Google, Meta, Vercel — hammasi monorepo).

Monorepo nima beradi: (1) umumiy kod oson (bir tip/komponentni barcha loyiha ishlatadi — bir joyda — o'zgartirsa hammasiga tarqaladi); (2) atomik o'zgarish (bir PR'da frontend + backend + umumiy — birga — izchil); (3) bir xil vositalar (lint, format, test — bir konfiguratsiya — 15.3); (4) oson refactoring (umumiy kodni o'zgartirsa — IDE barcha ishlatuvchini topadi). Lekin monorepo o'z muammolari bilan keladi (sekin build — butun loyiha, murakkab boshqaruv) — bularni Turborepo va Nx (monorepo vositalari — build kesh, faqat o'zgargan qismni build) hal qiladi. Bu bob monorepo nima, qachon, va vositalar (Turborepo/Nx)ni ko'rsatadi.

Bu bob monorepo mavzusini to'liq ochadi: monorepo vs polyrepo (farq, qachon), monorepo strukturasi (apps/packages), workspace (npm/pnpm/yarn — protocol workspace:*, hoisting, phantom dependency), umumiy kod (shared paketlar — internal paket, versiyalamasdan), Turborepo (build kesh — local/remote, pipeline dependsOn, filter, prune, incremental), Nx (generator, executor, affected, graph, plugin, integrated vs package-based), versiyalash (Changesets — fixed/independent), TypeScript monorepo (project references, path), CI (affected/changed-only, matrix), deploy (har app alohida — Vercel/Docker), va real misol (Next app + NestJS api + shared paket).

O'xshatish: Monorepo — bu bir umumiy ofis bino (ko'p jamoa, bir bino). Polyrepo — har jamoa alohida binoda (frontend binosi, backend binosi) — mustaqil, lekin umumiy resurs (printer, oshxona — umumiy kod)ni ulashish qiyin (har bino o'ziniki sotib oladi — nusxa). Monorepo — barcha jamoa bir binoda (qavatlar — apps/packages) — umumiy resurslar (lift, oshxona — shared kod) markaziy (bir marta — hammaga), jamoalar oson hamkorlik qiladi (bir binoda — bir PR'da). Lekin katta bino boshqaruvi murakkab (kim qaerda, qanday tartib) — Turborepo/Nx — bino menejeri (qaysi qavat o'zgardi — faqat o'shani yangila — butun binoni emas — build kesh). Monorepo — ko'p qismli loyihani bir joyda, umumiy kod bilan, samarali boshqarish.

Nega muhim?

  • Umumiy kod — tip/komponent/validatsiya barcha loyihada (bir joyda — DRY — 15.1).
  • Zamonaviy standart — katta loyiha (Google/Meta/Vercel — monorepo); full-stack (web+mobil+API).
  • Turborepo/Nx — monorepo muammosini (sekin build) hal qiladi (kesh, faqat o'zgargan).
  • Professional norma — ko'p kompaniya monorepo ishlatadi (bilish kerak).

2. Nazariya — chuqur tushuntirish

2.1. Monorepo vs polyrepo

text
  IKKI YONDASHUV — kodni qanday tashkil qilish:

  POLYREPO (har loyiha alohida repo):
  frontend-repo/  backend-repo/  mobile-repo/  shared-repo/
   mustaqil (har repo o'z hayoti, jamoasi)
   umumiy kod qiyin (npm paket yoki nusxa — sinxronlash murakkab)
   atomik o'zgarish qiyin (frontend+backend o'zgarish — 2 PR, 2 repo)

  MONOREPO (barcha bir repo):
  my-monorepo/
  ├── apps/        (ilovalar — web, mobile, api)
  ├── packages/    (umumiy kod — ui, types, config)
   umumiy kod oson (bir joyda — barcha app ishlatadi)
   atomik o'zgarish (frontend+backend+shared — bir PR)
   bir xil vositalar (lint/format/test — bir konfiguratsiya)
   sekin build (butun loyiha)  Turborepo/Nx hal qiladi (2.5)

   Polyrepo — alohida repo (mustaqil, umumiy kod qiyin); Monorepo — bir repo (umumiy oson)
   Monorepo — umumiy kod + atomik o'zgarish; muammosi (build) — Turborepo/Nx

Monorepo vs polyrepo — kodni tashkil qilishning ikki yondashuvi. Polyrepo (har loyiha alohida repozitoriy): frontend-repo, backend-repo, mobile-repo, shared-repo — har biri mustaqil. Afzalligi — mustaqillik (har repo o'z hayoti, jamoasi, deploy'i — alohida). Kamchiligi — umumiy kod qiyin (masalan TypeScript tiplari — frontend va backend ishlatadi — qanday ulashish? npm paket — har o'zgarishda nashr, versiyalash, o'rnatish — murakkab; yoki nusxa — sinxronlashmaydi — chalkash); atomik o'zgarish qiyin (frontend va backend birga o'zgarsa — masalan API maydoni qo'shilsa — 2 repo, 2 PR — birga deploy qiyin). Monorepo (barcha bir repozitoriyda): my-monorepo/ ichida apps/ (ilovalar — web, mobile, api) va packages/ (umumiy kod — ui, types, config). Afzalligi — umumiy kod oson (bir joyda — barcha app to'g'ridan ishlatadi — nashr/versiyalash yo'q); atomik o'zgarish (frontend + backend + shared — bir PR — izchil — masalan tip o'zgarsa, hamma joy bir vaqtda yangilanadi); bir xil vositalar (lint/format/test — bir konfiguratsiya — 15.3). Kamchiligi — sekin build (butun loyiha — minglab fayl) Turborepo/Nx hal qiladi (kesh, faqat o'zgargan — 2.5). Ikki nuqta: (1) polyrepo — alohida repo (mustaqil, lekin umumiy kod qiyin); monorepo — bir repo (umumiy kod oson, atomik o'zgarish); (2) monorepo — umumiy kod + atomik o'zgarish (afzalligi); muammosi (sekin build) — Turborepo/Nx hal qiladi. Qachon monorepo: ko'p loyiha umumiy kod ulashsa (full-stack — web + API + shared types; yoki ko'p ilova — web + mobil + admin — umumiy UI/logic). Qachon polyrepo: mustaqil loyihalar (umumiy kod kam — har biri alohida hayot). Zamonaviy katta loyiha (Google, Meta, Vercel) — monorepo (umumiy kod, izchillik). Tanlov — loyiha strukturasiga bog'liq (umumiy kod ko'pmi — monorepo).

2.2. Monorepo strukturasi

text
  MONOREPO STRUKTURASI — apps (ilovalar) + packages (umumiy):

  my-monorepo/
  ├── apps/                      # ILOVALAR (deploy qilinadigan)
  │   ├── web/                   # Next.js (web)
  │   ├── mobile/                # React Native
  │   └── api/                   # NestJS (backend)
  ├── packages/                  # UMUMIY KOD (apps ishlatadi)
  │   ├── ui/                    # umumiy React komponentlar
  │   ├── types/                 # umumiy TypeScript tiplari
  │   ├── validation/            # umumiy Zod sxemalari (frontend+backend)
  │   ├── config/                # umumiy ESLint/tsconfig 15.3-bob
  │   └── utils/                 # umumiy yordamchi funksiyalar
  ├── package.json               # root (workspace sozlamasi)
  ├── turbo.json                 # Turborepo 2.5-bob
  └── pnpm-workspace.yaml        # workspace 2.3-bob

  ISHLATISH (app shared paketni import qiladi):
  // apps/web/page.tsx
  import { Button } from "@repo/ui";          // packages/ui'dan
  import { UserSchema } from "@repo/validation"; // packages/validation'dan

   Monorepo — apps (ilovalar — deploy) + packages (umumiy kod — apps ishlatadi)
   App shared paketni import qiladi (@repo/ui) — umumiy kod bir joyda

Monorepo strukturasi — apps va packages tashkili. Monorepo ikki asosiy qismdan iborat: apps/ (ilovalar — deploy qilinadigan — masalan web — Next.js, mobile — React Native, api — NestJS) va packages/ (umumiy kod — apps ishlatadi — deploy qilinmaydi, balki apps ichida ishlatiladi). Tipik packages: ui (umumiy React komponentlar — Button, Card — web va mobil ishlatadi), types (umumiy TypeScript tiplari — User, Product — frontend va backend ishlatadi), validation (umumiy Zod sxemalari — bir validatsiya frontend va backend'da — 13.5: 2.9), config (umumiy ESLint/tsconfig — 15.3 — bir konfiguratsiya barcha app), utils (umumiy yordamchi funksiyalar). Root fayllar: package.json (workspace sozlamasi), turbo.json (Turborepo — 2.5), pnpm-workspace.yaml (workspace — 2.3). Ishlatish: app shared paketni import qiladi — import { Button } from "@repo/ui" (packages/ui'dan), import { UserSchema } from "@repo/validation" (packages/validation'dan) — @repo/ — workspace paketlari prefiksi (npm'dan emas — local monorepo'dan). Ikki nuqta: (1) monorepo — apps (ilovalar — deploy qilinadigan) + packages (umumiy kod — apps ishlatadi — deploy emas); (2) app shared paketni import qiladi (@repo/ui) — umumiy kod bir joyda (bir marta yoziladi, ko'p app ishlatadi — DRY — 15.1). Bu struktura — monorepo'ning standarti (apps/packages ajratish — ilova va umumiy kod). Eng katta afzallik — umumiy kod (packages/): masalan validation paketida UserSchema (Zod) — frontend (forma validatsiya — 11.10) va backend (API validatsiya — 13.5) bir sxemani ishlatadi (bir manba — o'zgartirsa ikkalasi to'g'ri — DRY); polyrepo'da bu nusxa yoki npm paket (murakkab). Bu struktura — full-stack monorepo'ning asosi (web + api + shared — bir joyda, umumiy kod bilan).

2.3. Workspace (npm / pnpm)

text
  WORKSPACE — paket menejeri monorepo'ni boshqarishi (paketlar bog'lanishi):

  WORKSPACE NIMA QILADI:
   packages/ va apps/ni "paketlar" deb taniydi (workspace)
   @repo/ui ni LOCAL paket sifatida bog'laydi (npm'dan emas — papka'dan)
   bir marta npm install (barcha paket bog'lanadi)

  PNPM WORKSPACE (eng tez, samarali — tavsiya):
  # pnpm-workspace.yaml:
  packages:
    - "apps/*"
    - "packages/*"

  ROOT package.json:
  {
    "name": "my-monorepo",
    "private": true,
    "workspaces": ["apps/*", "packages/*"]   // npm/yarn uchun
  }

  PAKET BOG'LANISHI (apps/web  packages/ui):
  // apps/web/package.json:
  { "dependencies": { "@repo/ui": "workspace:*" } }   // local workspace paket

   Workspace — paket menejeri (pnpm/npm) packages/apps'ni local paket deb bog'laydi
   @repo/ui = local (papka'dan, npm emas); workspace:* (versiya — local)

Workspace (npm / pnpm) — paket menejeri monorepo'ni boshqarishi. Workspace — paket menejeri (npm, yarn, pnpm)ning monorepo qo'llab-quvvatlashi: bir repozitoriyda ko'p paketni (apps + packages) boshqarish. Workspace nima qiladi: (1) packages/ va apps/ni "paketlar" deb taniydi (har papka — alohida paket — o'z package.jsoni bilan); (2) @repo/uini local paket sifatida bog'laydi (npm registry'dan emas — local papka'dan — packages/ui — to'g'ridan); (3) bir marta npm install (root'da) — barcha paketning bog'lanishi (apps shared paketlarga ulanadi). pnpm workspace (eng tez, samarali — disk tejaydi — tavsiya): pnpm-workspace.yamlpackages: ["apps/*", "packages/*"] (qaysi papkalar workspace). Root package.json: "private": true (root deploy qilinmaydi), "workspaces": ["apps/*", "packages/*"] (npm/yarn uchun). Paket bog'lanishi (apps/web packages/ui): apps/web/package.jsonda "@repo/ui": "workspace:*" (workspace:* — local workspace paket — npm'dan emas — packages/ui'dan — har doim eng yangi local versiya). Ikki nuqta: (1) workspace — paket menejeri (pnpm/npm) packages/apps'ni local paket deb bog'laydi (npm registry emas — local papka — to'g'ridan); (2) @repo/ui = local (papka'dan, npm emas), workspace:* (versiya — local — har doim eng yangi). Workspace — monorepo'ning texnik asosi (paketlar bir-biriga qanday bog'lanadi — local, npm emas). pnpm monorepo uchun eng yaxshi (tez, disk tejaydi — symlink bilan paketlarni ulashadi — npm'dan samaraliroq). Workspace bilan: @repo/uini o'zgartirsa — barcha ishlatuvchi app darrov yangi versiyani ko'radi (npm nashr/o'rnatish yo'q — local — to'g'ridan). Bu — monorepo'ning umumiy kod afzalligini 2.2-bob ishga tushiradi (workspace — bog'lanish mexanizmi). Bir install — butun monorepo bog'langan (apps shared paketlarni ishlatadi).

2.4. Umumiy kod (shared paketlar)

text
  UMUMIY KOD — bir marta yozish, ko'p app ishlatish (monorepo'ning yuragi):

  MISOL: validatsiya sxemasi (frontend + backend bir manba):
  // packages/validation/src/user.ts
  import { z } from "zod";
  export const UserSchema = z.object({
    email: z.string().email(),
    name: z.string().min(2),
  });
  export type User = z.infer<typeof UserSchema>;

  ISHLATISH (ikki joyda — bir manba):
  // apps/web (frontend — forma validatsiya — 11.10):
  import { UserSchema } from "@repo/validation";
  // apps/api (backend — API validatsiya — 13.5):
  import { UserSchema } from "@repo/validation";
  //  BIR sxema — o'zgartirsa IKKALA joy to'g'ri (DRY — 15.1)

  KENG SHARED PAKETLAR:
   types (umumiy tiplar) | ui (komponentlar) | validation (Zod)
   config (ESLint/tsconfig — 15.3) | utils (yordamchi) | api-client

   Umumiy kod — bir marta yoz (packages/), ko'p app ishlatadi (DRY — bir manba)
   Validatsiya/tip — frontend+backend BIR sxema (o'zgartirsa ikkalasi to'g'ri)

Umumiy kod (shared paketlar) — monorepo'ning eng katta afzalligi. Umumiy kod — bir marta yozish, ko'p app ishlatishi (DRY — 15.1 — monorepo darajasida). Misol (validatsiya sxemasi — frontend + backend bir manba): packages/validation/src/user.tsda UserSchema (Zod — email, name) + User tip (z.infer). Ishlatish (ikki joyda — bir manba): apps/web (frontend — forma validatsiya — RHF+Zod — 11.10) import { UserSchema } from "@repo/validation", va apps/api (backend — API validatsiya — 13.5: 2.9) xuddi shu import { UserSchema } from "@repo/validation"bir sxema, ikki joyda. Natija: agar validatsiya o'zgarsa (masalan name min 3 belgi) — packages/validationda bir joyda o'zgartiriladi, va frontend ham, backend ham avtomatik to'g'ri (bir manba — DRY). Polyrepo'da bu muammo (frontend va backend alohida — validatsiya nusxa yoki npm paket — sinxronlashmaydi — frontend min 2, backend min 3 — nomutanosiblik — bug). Monorepo'da — bir manba (izchil). Keng shared paketlar: types (umumiy tiplar — User, Product — frontend va backend), ui (React komponentlar — web va mobil), validation (Zod — frontend va backend), config (ESLint/tsconfig — 15.3 — bir konfiguratsiya), utils (yordamchi — formatlash, sana), api-client (API chaqiruvlar — frontend va mobil bir client). Ikki nuqta: (1) umumiy kod — bir marta yoziladi (packages/), ko'p app ishlatadi (DRY — bir manba — o'zgartirsa hamma joy); (2) validatsiya/tip — frontend + backend bir sxema (o'zgartirsa ikkalasi to'g'ri — izchillik — eng katta afzallik). Bu — monorepo'ning asosiy sababi (umumiy kod oson — bir joyda, izchil). Full-stack TypeScript loyihada (frontend + backend — bir til) — umumiy tip/validatsiya (end-to-end type safety — API tip frontend'da ham to'g'ri) — bu monorepo bilan oson (shared paket). Bu — kod takrorini (15.1: DRY) va nomutanosiblikni (frontend/backend farq) yo'qotadi. Umumiy kod — monorepo'ning yuragi.

2.5. Turborepo (build kesh, pipeline)

text
  TURBOREPO — monorepo build'ni TEZ qiladi (kesh, faqat o'zgargan):

  MUAMMO: monorepo'da butun loyihani build/test — SEKIN (barcha app+paket)
  YECHIM: Turborepo — kesh + faqat o'zgargan (o'zgarmaganni qayta build qilmaydi)

  TURBOREPO NIMA QILADI:
   KESH — bir marta build qilingan  keshdan (o'zgarmasa qayta build yo'q)
   FAQAT O'ZGARGAN — qaysi paket o'zgardi  faqat o'shani + bog'liqlarini
   PARALLEL — bog'liq bo'lmagan task'lar parallel (tez)
   REMOTE KESH — jamoa keshni ulashadi (CI ham — birovning build'i qayta ishlatiladi)

  SOZLASH (turbo.json — pipeline):
  {
    "tasks": {
      "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
      "test": { "dependsOn": ["build"] },
      "lint": {}
    }
  }
  // ^build — bog'liq paketlar avval build (to'g'ri tartib)

  ISHLATISH:
  turbo build       // barcha (lekin keshdan — tez)
  turbo build --filter=web   // faqat web (va bog'liqlari)

   Turborepo — build kesh + faqat o'zgargan (monorepo build sekinligini hal)
   Pipeline (turbo.json) — task tartibi (^build — bog'liqlar avval); remote kesh (jamoa)

Turborepo (build kesh, pipeline) — monorepo build'ni tezlashtirish. Muammo: monorepo'da butun loyihani build/test/lint qilish sekin (barcha app + paket — minglab fayl — har marta hammasi). Yechim — Turborepo (Vercel'ning monorepo vositasi): kesh + faqat o'zgargan qismni build. Turborepo nima qiladi: (1) kesh — bir marta build qilingan natija keshlanadi keyingi marta (o'zgarmasa) keshdan (qayta build yo'q — darrov); (2) faqat o'zgargan — qaysi paket o'zgardi (git diff bilan aniqlaydi) faqat o'shani va unga bog'liq paketlarni build (o'zgarmagan app'larni tegma); (3) parallel — bog'liq bo'lmagan task'lar parallel (masalan web build va api build — bog'liq emas — birga — tez); (4) remote kesh — jamoa keshni ulashadi (CI ham — agar bir dasturchi build qilgan bo'lsa, boshqasi (yoki CI) o'sha keshni ishlatadi — qayta build yo'q — juda tez). Sozlash (turbo.json — pipeline — task'lar tartibi): "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] } (^build — bog'liq paketlar avval build — masalan ui paketni build, keyin uni ishlatadigan web — to'g'ri tartib; outputs — kesh nima saqlaydi), "test": { "dependsOn": ["build"] } (test build'dan keyin), "lint": {} (bog'liqsiz). Ishlatish: turbo build (barcha — lekin keshdan — tez), turbo build --filter=web (faqat web va bog'liqlari). Ikki nuqta: (1) Turborepo — build kesh + faqat o'zgargan (monorepo build sekinligini hal qiladi — o'zgarmaganni qayta build qilmaydi); (2) pipeline (turbo.json) — task tartibi (^build — bog'liqlar avval), remote kesh (jamoa/CI keshni ulashadi). Turborepo — monorepo'ni amaliy qiladi (build sekinligi — eng katta monorepo muammosi — hal qilindi). Kesh eng muhim (o'zgarmagan kodni qayta build qilmaslik — katta vaqt tejash — masalan 10 ta app'dan 1 tasi o'zgarsa, faqat o'sha build, qolgani keshdan). Remote kesh — jamoa darajasida (birovning build'i — hammaga — CI tez). Turborepo sodda (kam sozlash — turbo.json + workspace), Vercel/Next.js bilan yaxshi integratsiya. Bu — monorepo'ning tezlik yechimi.

2.6. Nx va monorepo vositalari taqqoslash

text
  NX — kuchliroq monorepo vositasi (Turborepo'dan ko'proq imkoniyat):

  NX NIMA QO'SHADI (Turborepo'dan tashqari):
   Kesh + faqat o'zgargan (Turborepo kabi) + remote kesh
   KOD GENERATSIYA (generator — yangi app/component/lib avtomatik)
   BOG'LIQLIK GRAFI (qaysi paket nimaga bog'liq — vizual)
   PLUGIN ekotizimi (React, Next, NestJS, ... — integratsiya)
   "affected" — faqat o'zgarishga ta'sir qilgan test/build (CI tez)

  TURBOREPO vs NX:
   Turborepo: SODDA (kesh + pipeline — minimal, tez sozlash) — Vercel
   Nx: KUCHLI (generatsiya, plugin, graf — ko'p imkoniyat, lekin murakkabroq)

  QAYSI QACHON:
   Sodda monorepo (build kesh yetarli)  Turborepo
   Katta, murakkab (generatsiya, plugin, struktura)  Nx
   Boshlang'ich  Turborepo (oson)

   Nx — kuchli (generatsiya, plugin, graf); Turborepo — sodda (kesh, tez sozlash)
   Boshlang'ich/sodda  Turborepo; katta/murakkab  Nx

Nx va monorepo vositalari taqqoslash — Turborepo va Nx farqi. Nx — kuchliroq monorepo vositasi (Turborepo'dan ko'proq imkoniyat). Nx nima qo'shadi (Turborepo'dan tashqari): (1) kesh + faqat o'zgargan + remote kesh (Turborepo kabi — asosiy); (2) kod generatsiya (generator — nx generate bilan yangi app/component/library — avtomatik struktura, boilerplate — masalan yangi React komponent — papka, test, story avtomatik); (3) bog'liqlik grafi (qaysi paket nimaga bog'liq — vizual graf — katta monorepo'da foydali — bog'lanishlarni ko'rish); (4) plugin ekotizimi (React, Next.js, NestJS, Angular — har biri uchun integratsiya — sozlash avtomatik); (5) "affected" — faqat o'zgarishga ta'sir qilgan test/build (nx affected:test — faqat o'zgargan paketga bog'liq testlar — CI tez — Turborepo'ning "faqat o'zgargan"iga o'xshaydi, lekin kuchliroq). Turborepo vs Nx: Turborepo — sodda (kesh + pipeline — minimal sozlash, tez boshlash — Vercel); Nx — kuchli (generatsiya, plugin, graf — ko'p imkoniyat, lekin murakkabroq — o'rganish kerak). Qaysi qachon: sodda monorepo (build kesh yetarli — bir necha app) Turborepo (oson); katta, murakkab (ko'p app, generatsiya, struktura nazorati) Nx (kuchli); boshlang'ich Turborepo (oson kirish). Ikki nuqta: (1) Nx — kuchli (generatsiya, plugin, graf — enterprise); Turborepo — sodda (kesh, tez sozlash — minimal); (2) boshlang'ich/sodda Turborepo, katta/murakkab Nx. Ikkalasi ham monorepo'ni amaliy qiladi (build kesh — asosiy muammo). Tanlov — loyiha hajmi va ehtiyojga bog'liq (sodda — Turborepo; enterprise — Nx). Boshlang'ich uchun Turborepo tavsiya (oson — npx create-turbo — tayyor monorepo). Nx — keyin (katta loyiha, ko'p imkoniyat kerak bo'lganda). Ikkalasini ham bilish foydali (kompaniyalar ikkalasini ishlatadi). Bu — monorepo vositalari (har biri o'z o'rni — sodda vs kuchli).

2.7. Monorepo best practices va qachon

text
  MONOREPO BEST PRACTICES va QACHON:

  QACHON MONOREPO:
   Ko'p loyiha umumiy kod ulashsa (web+api+shared — tip/validatsiya)
   Full-stack TypeScript (end-to-end tip — frontend API tipini biladi)
   Ko'p ilova (web+mobil+admin — umumiy UI/logic)
   Mustaqil loyihalar (umumiy kod kam)  polyrepo

  BEST PRACTICES:
   apps/packages ajrat (ilova vs umumiy — 2.2)
   Workspace (pnpm afzal — tez — 2.3)
   Umumiy config (ESLint/tsconfig — packages/config — 15.3)
   Turborepo/Nx (build kesh — 2.5)
   Aniq bog'liqlik (app  package; package  package; aylanma yo'q)
   Versiyalash (Changesets — paket versiyalari)
   CI (faqat o'zgargan — affected — tez)

   Monorepo — ko'p loyiha + umumiy kod (web+api+shared); mustaqil  polyrepo
   Best — apps/packages + workspace + umumiy config + Turborepo + aniq bog'liqlik

Monorepo best practices va qachon — monorepo'ni to'g'ri ishlatish. Qachon monorepo: (1) ko'p loyiha umumiy kod ulashsa (web + api + shared — tip/validatsiya — 2.4 — eng keng sabab); (2) full-stack TypeScript (end-to-end tip safety — frontend backend API tipini biladi — bir til, bir repo — umumiy tip); (3) ko'p ilova (web + mobil + admin panel — umumiy UI/logic/auth). Qachon polyrepo (monorepo emas): mustaqil loyihalar (umumiy kod kam — har biri alohida hayot, jamoa, deploy — monorepo ortiqcha murakkablik). Best practices: (1) apps/packages ajrat (ilova — deploy vs umumiy kod — 2.2 — aniq struktura); (2) workspace (pnpm afzal — tez, disk tejaydi — 2.3); (3) umumiy config (ESLint/tsconfig — packages/config — bir konfiguratsiya barcha app — 15.3 — izchillik); (4) Turborepo/Nx (build kesh — sekin build muammosi — 2.5); (5) aniq bog'liqlik (app package — to'g'ri; package package — OK; aylanma bog'liqlik yo'q — ui utils ui — taqiqlangan — chalkash); (6) versiyalash (Changesets — agar paketlar npm'ga nashr qilinsa — versiyalar boshqaruvi); (7) CI (faqat o'zgargan — affected — Turborepo/Nx — tez — butun monorepo emas). Ikki nuqta: (1) monorepo — ko'p loyiha + umumiy kod (web + api + shared — umumiy tip/validatsiya); mustaqil loyiha (umumiy kod kam) polyrepo; (2) best — apps/packages + workspace + umumiy config + Turborepo + aniq bog'liqlik. Monorepo — kuchli, lekin har loyiha uchun emas (kichik, bitta ilova — monorepo ortiqcha — oddiy repo yetadi). Monorepo qiymati — umumiy kod (ko'p loyiha bir kodni ulashsa). Agar umumiy kod kam (mustaqil loyiha) — polyrepo soddaroq. To'g'ri tanlov (monorepo vs polyrepo) — loyiha strukturasiga bog'liq (umumiy kod ko'pmi — monorepo). Boshlang'ich uchun — oddiy repo (monorepo keyin — loyiha o'sgani, umumiy kod paydo bo'lganda). Monorepo — full-stack, ko'p loyihali ishni soddalashtiruvchi kuchli yondashuv (to'g'ri ishlatilsa — umumiy kod, izchillik, atomik o'zgarish; vositalar bilan — tez build). Bu — zamonaviy katta loyiha boshqaruvining asosiy ko'nikmasi.

2.8. Workspace chuqurroq — hoisting, phantom dependency, protocol

text
  WORKSPACE ICHKI ISHLASHI — hoisting va phantom dependency:

  HOISTING (npm/yarn — flat node_modules):
   barcha paket dependency'lari ROOT node_modules'ga ko'tariladi (hoist)
   apps/web zod'ni package.json'da yozmasa ham, root'da bor  import ishlaydi (!)
   BU XAVFLI: "phantom dependency" (e'lon qilinmagan, lekin ishlaydi)
   yakka deploy'da (faqat web) zod yo'q  SINADI (root'siz)

  PNPM (symlink + izolyatsiya — phantom'ni bloklaydi):
   har paket faqat OZ package.json'dagi dependency'ni ko'radi (qat'iy)
   node_modules symlink strukturasi (.pnpm store — bir nusxa diskda)
   phantom dependency imkonsiz (e'lon qilmagan paketni import qilolmaysiz)

  PROTOCOL — workspace paketlarga havola:
  "@repo/ui": "workspace:*"       har doim eng yangi local (versiya e'tiborsiz)
  "@repo/ui": "workspace:^"       local, lekin publish'da ^1.2.0 ga aylanadi
  "@repo/ui": "workspace:1.2.0"   aniq local versiya

   npm/yarn hoisting  phantom dependency xavfi; pnpm izolyatsiya  xavfsiz
   workspace:* — local paket (publish'da real versiyaga almashtiriladi)

Workspace chuqurroq — hoisting mexanizmi va phantom dependency muammosi. Hoisting (npm va yarn classic'da): monorepo'da har paketning dependencieslari root node_modulesga ko'tariladi (hoist qilinadi — flat struktura — bir joyda). Buning yon ta'siri — phantom dependency: apps/web o'z package.jsonida zodni e'lon qilmasa ham, boshqa paket (masalan packages/validation) uni root'ga hoist qilgani uchun, apps/webda import { z } from "zod" ishlab ketadi — lekin bu xavfli: webni yakka deploy qilganda (faqat apps/web — root'siz — masalan Docker'da bitta app) zod topilmaydi build sinadi; yoki validation zoddan voz kechsa — web sababsiz sinadi. pnpm buni hal qiladi: symlink asosli, izolyatsiyalangan node_modules (har paket faqat o'z package.jsonidagi dependency'ni ko'radi — qat'iy); haqiqiy fayllar node_modules/.pnpm store'da bir nusxa (disk tejaydi — content-addressable), qolgani symlink. Natijada phantom dependency imkonsiz — e'lon qilmagan paketni import qilolmaysiz (xatoni erta ushlaydi). Shuning uchun monorepo uchun pnpm tavsiya (izolyatsiya + tezlik + disk). Protocol — workspace paketlarga havola turlari: workspace:* (har doim eng yangi local — versiya e'tiborsiz — ichki paket uchun eng keng), workspace:^ (local, lekin npm publishda ^1.2.0ga avtomatik aylanadi — tashqi nashr uchun), workspace:1.2.0 (aniq local versiya). Ikki nuqta: (1) npm/yarn hoisting phantom dependency (e'lon qilinmagan, lekin ishlaydi — deploy'da sinadi); pnpm izolyatsiya xavfsiz; (2) workspace:* — local bog'lanish, publishda real versiyaga almashtiriladi. Bu — workspace'ning texnik chuqurligi (nega pnpm afzal — phantom'ni bloklaydi, izolyatsiya).

2.9. Turborepo chuqurroq — remote cache, filter, prune

text
  TURBOREPO CHUQUR — kesh hash, remote cache, filter, prune:

  KESH QANDAY ISHLAYDI (hash asosli):
   Turbo har task uchun HASH hisoblaydi:
    fayllar (input) + dependency'lar + env + config  hash
   hash o'zgarmasa  keshdan (build/test qayta ishlamaydi)
   hash o'zgarsa  qayta ishlaydi + yangi keshni saqlaydi

  LOCAL vs REMOTE cache:
   LOCAL: .turbo/ papka (o'z mashinangda)
   REMOTE: bulut (Vercel yoki o'z serverda)  JAMOA ulashadi
    turbo login && turbo link  (Vercel remote cache'ni yoqadi)
   CI ham remote'dan oladi: dasturchi build qilgan  CI qayta build qilmaydi

  FILTER (nimani ishga tushirish):
  turbo build --filter=web              # faqat web
  turbo build --filter=web...           # web + unga BOG'LIQ (downstream)
  turbo build --filter=...web           # web + web BOG'LIQLARI (upstream)
  turbo build --filter='[main]'         # main'dan beri o'zgargan (git)

  PRUNE (deploy uchun kichraytirish):
  turbo prune web --docker
   faqat web + uning dependency'lari qolgan minimal monorepo (Docker uchun)

   Kesh = hash (input+dep+env); remote cache = jamoa/CI ulashadi (juda tez)
   filter — nimani ishga tushirish; prune — deploy uchun minimal subset

Turborepo chuqurroq — kesh mexanizmi, remote cache, filter va prune. Kesh qanday ishlaydi (hash asosli): Turbo har task (masalan web#build) uchun hash hisoblaydi — task input'lari (manba fayllar), unga bog'liq paketlar, muhit o'zgaruvchilari (env), va konfiguratsiya asosida. Agar hash o'zgarmasa (hech narsa o'zgarmagan) natijani keshdan oladi (build/test qayta ishlamaydi — darrov); hash o'zgarsa qayta ishlaydi va yangi keshni saqlaydi. Shuning uchun turbo.jsonda outputs (kesh nima saqlaydi — dist/**) va inputs/env to'g'ri bo'lishi muhim (aks holda kesh noto'g'ri ishlaydi — masalan env o'zgarsa lekin hisobga olinmasa — eski natija). Local vs remote cache: local — .turbo/ papka (o'z mashinangizda — takroriy build tez); remote — bulutda (Vercel yoki o'z serveringizda — turbo login && turbo link) jamoa ulashadi: bir dasturchi build qilgan natijani boshqa dasturchi yoki CI qayta ishlatadi (qayta build yo'q — CI juda tez — bu remote cache'ning asosiy qiymati). Filter (nimani ishga tushirish): --filter=web (faqat web), --filter=web... (web + unga bog'liq — downstream — web o'zgarsa uni ishlatadigan app'lar), --filter=...web (web + web bog'liqlari — upstream — web ishlatadigan paketlar), --filter='[main]' (main branch'dan beri git'da o'zgargan paketlar — CI'da eng keng). Prune (deploy uchun): turbo prune web --docker faqat web va uning dependency'lari qolgan minimal monorepo subset yaratadi (Docker image uchun — kichik, tez build — butun monorepo emas). Ikki nuqta: (1) kesh = hash (input + dependency + env + config); remote cache = jamoa/CI keshni ulashadi (juda katta tezlik); (2) filter — nimani ishga tushirish (git diff'gacha); prune — deploy uchun minimal subset. Bu — Turborepo'ning amaliy chuqurligi (kesh to'g'ri sozlash, remote cache jamoa uchun, filter/prune CI va deploy uchun).

2.10. Nx chuqurroq — generator, executor, affected, integrated vs package-based

text
  NX CHUQUR — generator/executor, affected, integrated vs package-based:

  GENERATOR (kod yaratish — skaffold):
  nx g @nx/react:app web           # yangi React app (tayyor struktura)
  nx g @nx/react:lib ui            # yangi kutubxona
  nx g @nx/react:component Button --project=ui   # komponent (test bilan)

  EXECUTOR (task bajaruvchi — build/test/serve):
   har target (build, test, serve) bir executor'ni chaqiradi
   project.json: "build": { "executor": "@nx/vite:build", ... }

  AFFECTED (faqat o'zgarishga ta'sir qilgan):
  nx affected -t build             # o'zgargan + unga bog'liq loyihalar build
  nx affected -t test --base=main  # main'ga nisbatan o'zgargan testlar
   dependency GRAF orqali "ta'sir doirasi"ni aniqlaydi

  INTEGRATED vs PACKAGE-BASED:
   package-based: har app o'z package.json/dependency (Turbo'ga o'xshash — yengil)
   integrated: Nx boshqaradi (bir versiya, generator/executor to'liq — enterprise)

  NX CLOUD: remote cache + CI'da task taqsimlash (distributed) + affected

   Nx = generator (kod yaratish) + executor (task) + affected (graf asosli)
   integrated (Nx to'liq boshqaradi) vs package-based (yengil, Turbo kabi)

Nx chuqurroq — generator, executor, affected va ikki rejim. Generator (nx g — kod skaffold): tayyor struktura yaratadi — nx g @nx/react:app web (yangi React app — barcha config bilan), nx g @nx/react:lib ui (kutubxona), nx g @nx/react:component Button --project=ui (komponent + test + boilerplate). Bu boilerplate'ni yo'qotadi (izchil struktura — hamma app bir xil). Executor (task bajaruvchi): Nx'da har target (build, test, serve, lint) bir executor'ni chaqiradi — project.jsonda "build": { "executor": "@nx/vite:build", "options": {...} } (executor — task qanday bajarilishini biladi — plugin bilan keladi). Turborepo'da task = npm script; Nx'da task = executor (kuchliroq, lekin abstraktroq). Affected (faqat o'zgarishga ta'sir qilgan): nx affected -t build (o'zgargan paketlar va ularga bog'liq paketlar — dependency grafi orqali "ta'sir doirasi"ni aniqlaydi), nx affected -t test --base=main (mainga nisbatan). Bu CI'da eng muhim — butun monorepo emas, faqat ta'sirlangan qismni test/build (tez). Integrated vs package-based (Nx'ning ikki rejimi): package-based — har app o'z package.json/dependency'siga ega (Turborepo'ga o'xshash — yengil, mavjud loyihaga qo'shish oson); integrated — Nx to'liq boshqaradi (bir versiya barcha paketga, generator/executor to'liq ishlaydi, qat'iy struktura — enterprise, katta jamoa). Nx Cloud — remote cache (Turbo remote cache kabi) + CI'da task'larni bir necha mashinaga taqsimlash (distributed task execution — juda katta monorepo uchun) + affected. Ikki nuqta: (1) Nx = generator (kod yaratish) + executor (task bajarish) + affected (graf asosli ta'sir doirasi); (2) integrated (Nx to'liq boshqaradi — enterprise) vs package-based (yengil — Turbo kabi). Bu — Nx'ning Turborepo'dan farqi (ko'proq abstraksiya va imkoniyat, lekin murakkabroq).

Qaysi qachon — Turborepo vs Nx (jadval):

Mezon Turborepo Nx
Murakkablik Sodda (kam sozlash) Murakkabroq (o'rganish kerak)
Kod generatsiya Yo'q Bor (generator)
Task modeli npm script Executor (plugin)
Kesh + remote Bor (Vercel) Bor (Nx Cloud)
Affected/o'zgargan --filter='[main]' nx affected (graf)
Plugin ekotizim Kam Boy (React/Nest/Angular…)
CI taqsimlash Yo'q Bor (Nx Cloud DTE)
Eng mos Sodda/o'rta monorepo, Next.js/Vercel Katta/enterprise, ko'p app, struktura nazorati
Boshlash npx create-turbo npx create-nx-workspace

2.11. Versiyalash — Changesets (fixed vs independent)

text
  VERSIYALASH — agar paketlar npm'ga NASHR qilinsa (Changesets):

  MUAMMO: qaysi paket o'zgardi? qaysi versiya? changelog kim yozadi?
  YECHIM: Changesets — o'zgarishlarni belgilash + versiya + publish

  ISH OQIMI:
  npx changeset          # o'zgargan paket + tur (patch/minor/major) + izoh
   .changeset/*.md fayl yaratadi (PR bilan birga commit)
  npx changeset version  # changeset'larni yig'ib versiya + CHANGELOG yangilaydi
  npx changeset publish   # npm'ga nashr (o'zgargan paketlar)

  FIXED vs INDEPENDENT:
   FIXED (lockstep): barcha paket BIR versiya (biri o'zgarsa hammasi ko'tariladi)
   INDEPENDENT: har paket O'Z versiyasi (faqat o'zgargani ko'tariladi — keng)

   Changesets — o'zgarishni belgilash  versiya  changelog  publish (avtomatik)
   fixed (hammasi bir versiya) vs independent (har paket alohida)

Versiyalash — Changesets — paketlarni npm'ga nashr qilishda versiya boshqaruvi. Agar monorepo paketlari tashqi (npm'ga nashr — masalan ochiq kutubxona yoki jamoalararo paket) bo'lsa — muammo: qaysi paket o'zgardi, qaysi versiya (patch/minor/major), changelog kim yozadi. Changesets buni hal qiladi. Ish oqimi: (1) npx changeset — o'zgargan paketni tanlash, o'zgarish turini (SemVer — patch tuzatish, minor yangi imkoniyat, major buzuvchi o'zgarish) va izohni kiritish .changeset/*.md fayl yaratadi (PR bilan birga commit — o'zgarish "niyati" saqlanadi); (2) npx changeset version — yig'ilgan changeset'larni hisobga olib paket versiyalarini ko'taradi va CHANGELOG.mdni avtomatik yangilaydi; (3) npx changeset publish — o'zgargan paketlarni npm'ga nashr qiladi (odatda CI'da, mainga merge'dan keyin). Fixed vs independent: fixed (lockstep) — barcha paket bir versiya (biri o'zgarsa hammasi ko'tariladi — masalan bir tanlangan kutubxona oilasi — Angular kabi); independent — har paket o'z versiyasi (faqat o'zgargani ko'tariladi — eng keng — mustaqil paketlar). Ikki nuqta: (1) Changesets — o'zgarishni belgilash versiya changelog publish (avtomatik, izchil); (2) fixed (hammasi bir versiya) vs independent (har paket alohida). Muhim: agar paketlar faqat ichki (npm'ga nashr yo'q — 2.4 — workspace:* bilan to'g'ridan ishlatiladi) — versiyalash kerak emas (Changesets ortiqcha). Changesets faqat nashr qilinadigan paketlar uchun (ichki apps/ deploy qilinadi — versiyalanmaydi).

2.12. TypeScript monorepo — project references va path

text
  TYPESCRIPT MONOREPO — project references va path mapping:

  IKKI YONDASHUV umumiy tipni ulashish uchun:

  1) PATH (tsconfig paths — sodda, source'ni to'g'ridan ishlatadi):
  // tsconfig.base.json:
  { "compilerOptions": {
      "paths": { "@repo/*": ["packages/*/src"] } } }
   @repo/ui import  packages/ui/src (build kerak emas — dev tez)

  2) PROJECT REFERENCES (katta loyiha — inkremental build):
  // apps/web/tsconfig.json:
  { "references": [{ "path": "../../packages/ui" }] }
   tsc --build  bog'liq paketlarni to'g'ri tartibda inkremental build
   har paketda "composite": true kerak

   paths — sodda (source to'g'ridan, dev tez); references — inkremental (katta)
   Turbo/Nx build tartibini boshqaradi; TS references type-check tartibini

TypeScript monorepo — umumiy tiplarni ulashning ikki yondashuvi. 1) Path mapping (sodda — eng keng): tsconfig.base.jsonda "paths": { "@repo/*": ["packages/*/src"] }@repo/ui importi to'g'ridan packages/ui/srcga xaritalanadi (build kerak emas — TypeScript source'ni to'g'ridan o'qiydi — dev'da tez, create-turbo shu usulda). Kamchiligi — juda katta loyihada type-check sekinlashadi (hamma source qayta o'qiladi). 2) Project references (katta loyiha — inkremental): har paket alohida TS "loyiha" sifatida, apps/web/tsconfig.jsonda "references": [{ "path": "../../packages/ui" }] (web uiga bog'liq), va har bog'liq paketda "composite": true. tsc --build (build mode) bog'liq paketlarni to'g'ri tartibda va inkremental (faqat o'zgargan) type-check/build qiladi (.tsbuildinfo bilan). Bu — juda katta monorepo'da type-check tezligini beradi. Ikki nuqta: (1) paths — sodda (source to'g'ridan, dev tez — boshlang'ich); references — inkremental type-check (katta loyiha); (2) Turborepo/Nx build/task tartibini boshqaradi, TS project references esa type-check tartibini (ikkalasi bir-birini to'ldiradi — Turbo task graf, TS tip graf). Boshlang'ich uchun paths yetadi (create-turbo default), project references keyin (loyiha juda o'sganda).

2.13. CI va deploy — affected/matrix va har app alohida

text
  MONOREPO CI va DEPLOY:

  CI (faqat o'zgargan — tez):
   Turbo: turbo run build test lint --filter='[origin/main]'
   Nx:    nx affected -t build test lint --base=origin/main
   remote cache: birov build qilgan  CI keshdan (qayta build yo'q)
   matrix: har app parallel job (GitHub Actions matrix — 10.5)

  DEPLOY (har app ALOHIDA — mustaqil):
   apps/web  Vercel (root: apps/web, build: turbo build --filter=web)
   apps/api  Docker:
      turbo prune api --docker    # minimal subset
      Docker build (faqat api + dependency'lari)
   har app o'z quvuri (bir monorepo, ko'p deploy target)

   CI — affected/filter + remote cache (faqat o'zgargan, kesh — tez)
   Deploy — har app alohida (Vercel web, Docker api) — bir repo, ko'p target

CI va deploy — monorepo'ni ishlab chiqarishga chiqarish. CI (faqat o'zgargan — tez): butun monorepo'ni har push'da build/test qilish sekin — shuning uchun affected/filter ishlatiladi — Turborepo: turbo run build test lint --filter='[origin/main]' (maindan beri o'zgargan paketlar va ular bog'liqlari); Nx: nx affected -t build test lint --base=origin/main. Ustiga remote cache 2.9-bob — agar bir dasturchi allaqachon build qilgan bo'lsa, CI keshdan oladi (qayta build yo'q — juda tez). Matrix (10.5 — GitHub Actions) — har app'ni parallel job'da ishga tushirish mumkin (web, api, mobile — bir vaqtda — tezroq CI). Deploy (har app alohida — mustaqil): monorepo bir repo, lekin har app alohida deploy target — apps/web Vercel (Root Directory: apps/web, Build Command: turbo build --filter=web — Vercel monorepo'ni tushunadi); apps/api Docker: avval turbo prune api --docker (faqat api + dependency'lari qolgan minimal subset — 2.9), keyin shu subset'dan Docker image (kichik, tez). Har app o'z CI/CD quvuriga ega (bir monorepo ko'p deploy target — web bir joyga, api boshqa joyga). Ikki nuqta: (1) CI — affected/filter + remote cache (faqat o'zgargan qismni build/test, kesh — tez — butun monorepo emas); (2) deploy — har app alohida (Vercel web uchun, Docker api uchun) — bir repo, ko'p deploy target. Bu — monorepo'ning ishlab chiqarish jihati (CI tez — affected + kesh; deploy moslashuvchan — har app o'z quvuri).


3. Sintaksis — monorepo ma'lumotnoma

text
STRUKTURA 2.2-bob:  apps/ (web, api, mobile) + packages/ (ui, types, validation, config)
WORKSPACE 2.3-bob:  pnpm-workspace.yaml (packages: apps/*, packages/*) | package.json workspaces
BOG'LANISH 2.3-bob: "@repo/ui": "workspace:*" (local); workspace:^ (publish'da real versiya)
PHANTOM 2.8-bob:    npm/yarn hoisting  phantom dependency; pnpm izolyatsiya  xavfsiz
IMPORT 2.4-bob:     import { Button } from "@repo/ui"
TURBO (2.5,2.9):  turbo.json (tasks: build dependsOn ^build, outputs, cache, persistent)
TURBO FILTER:     turbo build --filter=web | --filter=web... | --filter='[main]'
TURBO PRUNE:      turbo prune web --docker (deploy uchun minimal subset)
REMOTE CACHE:     turbo login && turbo link (jamoa/CI keshni ulashadi)
NX (2.6,2.10):    nx g (generator), nx affected -t build --base=main, executor, graf
VERSIYA 2.11-bob:   changeset  changeset version  changeset publish (fixed/independent)
TS 2.12-bob:        tsconfig paths (@repo/*  packages/*/src) | project references (composite)
CI/DEPLOY 2.13-bob: affected/filter + remote cache; Vercel (web), Docker+prune (api)
QACHON 2.7-bob:     ko'p loyiha + umumiy kod  monorepo; mustaqil  polyrepo

4. Batafsil misollar

Har misol: Maqsad + sozlash/kod + "Bu nima qiladi".

Misol 1 — Monorepo strukturasi yaratish (2.2, 2.3)

Maqsad: Turborepo bilan monorepo yaratish va strukturasini sozlash. Bu full-stack monorepo'ning poydevori.

bash
# Turborepo bilan monorepo yaratish:
npx create-turbo@latest my-monorepo
cd my-monorepo

# Struktura (avtomatik yaratiladi):
# my-monorepo/
# ├── apps/web/ apps/docs/   (Next.js ilovalar)
# ├── packages/ui/           (umumiy komponentlar)
# ├── packages/eslint-config/  (umumiy ESLint — 15.3)
# ├── packages/typescript-config/ (umumiy tsconfig)
# ├── turbo.json  package.json  pnpm-workspace.yaml
yaml
# pnpm-workspace.yaml:
packages:
  - "apps/*"
  - "packages/*"
json
// package.json (root):
{
  "name": "my-monorepo",
  "private": true,
  "scripts": {
    "build": "turbo build",
    "dev": "turbo dev",
    "lint": "turbo lint"
  },
  "devDependencies": { "turbo": "^2.0.0" }
}

Bu nima qiladi: Bu — Turborepo monorepo yaratish (2.2, 2.3). npx create-turbo@latest — Vercel'ning monorepo skaffold vositasi (tayyor struktura — apps + packages + Turborepo sozlangan). Struktura (avtomatik): apps/ (web, docs — Next.js ilovalar — deploy qilinadigan), packages/ (ui — umumiy komponentlar, eslint-config — umumiy ESLint — 15.3, typescript-config — umumiy tsconfig), va root fayllar (turbo.json, package.json, pnpm-workspace.yaml). pnpm-workspace.yaml — workspace sozlamasi (apps/* va packages/* — qaysi papkalar paket — 2.3). Root package.json"private": true (root deploy emas), scripts (turbo build — barcha app build, turbo dev — barcha dev, turbo lint — barcha lint — bir buyruq, butun monorepo), Turborepo dependency. Nima qiladi: bir buyruq (create-turbo) bilan to'liq monorepo — apps (ilovalar), packages (umumiy kod), workspace (bog'lanish), Turborepo (build kesh — 2.5), umumiy config (ESLint/tsconfig — 15.3) — hammasi tayyor. Endi: npm run build (root'da) Turborepo barcha app'ni build qiladi (kesh bilan — tez), apps/web packages/uini ishlatadi (umumiy komponent). Nega create-turbo: monorepo'ni qo'lda sozlash murakkab (workspace, Turborepo, umumiy config — ko'p fayl) — create-turbo tayyor, ishlaydigan strukturani beradi (best practice bilan — apps/packages, umumiy config). Bu — monorepo boshlashning eng oson usuli (Turborepo — Next.js/Vercel bilan yaxshi). Keyin: o'z app/packages'ni qo'shasiz (masalan apps/api — NestJS, packages/validation — Zod). Bu monorepo'ning poydevori (struktura + workspace + Turborepo — tayyor).

Misol 2 — Umumiy paket yaratish (validation — 2.4)

Maqsad: Frontend va backend ishlatadigan umumiy validatsiya paketi yaratish. Bu monorepo'ning eng katta afzalligi (bir manba).

json
// packages/validation/package.json:
{
  "name": "@repo/validation",
  "version": "0.0.0",
  "main": "./src/index.ts",
  "types": "./src/index.ts",
  "dependencies": { "zod": "^3.23.0" }
}
tsx
// packages/validation/src/index.ts — umumiy Zod sxemalar:
import { z } from "zod";

export const UserSchema = z.object({
  email: z.string().email("Email noto'g'ri"),
  name: z.string().min(2, "Ism kamida 2 harf"),
  age: z.number().min(18, "18 yoshdan katta"),
});
export type User = z.infer<typeof UserSchema>;

export const ProductSchema = z.object({
  title: z.string().min(3),
  price: z.number().positive(),
});
export type Product = z.infer<typeof ProductSchema>;
tsx
// ISHLATISH — ikki app, bir sxema:
// apps/web (frontend — RHF validatsiya — 11.10):
import { UserSchema } from "@repo/validation";
const form = useForm({ resolver: zodResolver(UserSchema) });

// apps/api (backend — API validatsiya — 13.5):
import { UserSchema } from "@repo/validation";
const result = UserSchema.safeParse(req.body);

Bu nima qiladi: Bu — umumiy validatsiya paketi (monorepo'ning eng katta afzalligi — bir manba — 2.4). packages/validation/package.json — paket ta'rifi: "name": "@repo/validation" (workspace paket nomi — @repo/ prefiksi), "main"/"types" (kirish nuqtasi — src/index.ts — TypeScript to'g'ridan, build kerak emas — monorepo'da source ulashish mumkin), zod dependency. packages/validation/src/index.ts — umumiy Zod sxemalar (UserSchema — email, name, age + User tip; ProductSchema + Product tip) — bu bir joyda (validatsiya logikasi). Ishlatish (ikki app, bir sxema): apps/web (frontend — React Hook Form + Zod — 11.10 — zodResolver(UserSchema)) va apps/api (backend — API validatsiya — 13.5: 2.9 — UserSchema.safeParse(req.body)) — xuddi shu UserSchemani import qiladi (@repo/validation'dan). Nima qiladi: validatsiya bir manba (packages/validation) — frontend va backend ishlatadi. Agar qoida o'zgarsa (masalan name min 3 belgi) — packages/validationda bir joyda o'zgartiriladi frontend (forma) va backend (API) avtomatik to'g'ri (workspace — local — to'g'ridan — nashr/o'rnatish yo'q). Nega bu kuchli: (1) DRY (15.1 — bir validatsiya — ikki joy emas — takror yo'q); (2) izchillik (frontend va backend bir xil qoida — nomutanosiblik yo'q — masalan frontend min 2, backend min 3 bo'lmaydi — bir manba); (3) end-to-end type safety (User tip ham umumiy — frontend va backend bir tip — API javobi frontend'da to'g'ri tip). Polyrepo'da bu muammo (frontend/backend alohida repo — validatsiya nusxa yoki npm paket — sinxronlashmaydi — nomutanosiblik — bug). Monorepo + shared paket — bir manba (izchil, DRY). Bu — monorepo'ning asosiy qiymati (umumiy kod — 2.4). Validatsiya — eng keng misol (frontend va backend bir validatsiya), lekin tip, UI komponent, utils ham (umumiy). Bu — full-stack monorepo'ning kuchi (umumiy kod — izchil, takrorsiz).

Misol 3 — Turborepo pipeline (2.5)

Maqsad: Turborepo pipeline sozlash — build tartibi va kesh. Bu monorepo build'ni tez va to'g'ri qiladi.

json
// turbo.json — task pipeline:
{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],        // bog'liq paketlar AVVAL build (ui  web)
      "outputs": ["dist/**", ".next/**"]  // kesh nima saqlaydi
    },
    "test": {
      "dependsOn": ["build"]          // test build'dan keyin
    },
    "lint": {},                       // bog'liqsiz (parallel)
    "dev": {
      "cache": false,                 // dev keshlanmaydi (doimo yangi)
      "persistent": true              // dev server uzluksiz
    }
  }
}
bash
# Ishlatish:
turbo build                  # barcha (kesh bilan — o'zgarmagani keshdan — tez)
turbo build --filter=web     # faqat web + bog'liqlari (ui)
turbo test --filter=...^web  # web'ga bog'liq paketlar testi

# KESH NATIJASI:
$ turbo build                # 1-marta: 45s (hammasi build)
$ turbo build                # 2-marta (o'zgarmagan): 0.2s (KESHDAN — FULL TURBO)
$ # web o'zgardi:
$ turbo build                # faqat web build (ui keshdan): 8s

Bu nima qiladi: Bu — Turborepo pipeline (build tartibi va kesh — 2.5). turbo.json — task'lar pipeline (qaysi task qanday ishlaydi): (1) build"dependsOn": ["^build"] (^buildbog'liq paketlarni avval build — masalan web uini ishlatadi, shuning uchun ui avval build, keyin web — to'g'ri tartib), "outputs": ["dist/**", ".next/**"] (kesh nima saqlaydi — build natijasi — keyingi marta keshdan); (2) test"dependsOn": ["build"] (test build'dan keyin — build natijasini sinaydi); (3) lint — bog'liqsiz (parallel — boshqa task kutmaydi); (4) dev"cache": false (dev keshlanmaydi — doimo yangi — kod o'zgaradi), "persistent": true (dev server uzluksiz ishlaydi). Ishlatish: turbo build (barcha — kesh bilan), turbo build --filter=web (faqat web + bog'liqlari), turbo test --filter=...^web (web'ga bog'liq testlar). Kesh natijasi (eng muhim): 1-marta turbo build — 45s (hammasi build); 2-marta (o'zgarmagan) — 0.2s (keshdan — "FULL TURBO" — hech narsa o'zgarmagani uchun qayta build yo'q); web o'zgarsa — faqat web build (8s), ui keshdan (o'zgarmagan). Nima qiladi: Turborepo monorepo build'ni tez qiladi (kesh — o'zgarmaganni qayta build qilmaydi; faqat o'zgargan — o'zgargan paket va bog'liqlari). Nega bu muhim: monorepo'ning eng katta muammosi — sekin build (barcha app — minglab fayl); Turborepo kesh bilan buni hal qiladi (o'zgarmagan — keshdan — 0.2s; o'zgargan — faqat o'sha — tez). Pipeline (dependsOn) — to'g'ri tartib (ui avval, keyin web^build). Bu monorepo'ni amaliy qiladi (build tez — katta monorepo ham ishlaydi). Remote kesh (2.5 — Vercel) — jamoa/CI keshni ulashadi (yanada tez). Turborepo — monorepo'ning tezlik dvigateli (kesh + faqat o'zgargan + parallel). turbo.json — sodda (kam sozlash — task'lar + bog'liqlik), lekin katta ta'sir (45s 0.2s). Bu — monorepo build optimizatsiyasi (kesh — eng muhim).

Misol 4 — Umumiy config paketi (2.7, 15.3)

Maqsad: ESLint/tsconfig'ni umumiy paket sifatida ulashish. Bu barcha app bir xil sozlamada (izchillik — 15.3).

json
// packages/eslint-config/package.json:
{
  "name": "@repo/eslint-config",
  "version": "0.0.0",
  "main": "index.js"
}
tsx
// packages/eslint-config/index.js — umumiy ESLint 15.3-bob:
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import prettier from "eslint-config-prettier";

export const baseConfig = [
  js.configs.recommended,
  ...tseslint.configs.recommended,
  { rules: { "eqeqeq": "error", "no-unused-vars": "error" } },
  prettier,
];
tsx
// apps/web/eslint.config.js — umumiy config'ni ishlatadi:
import { baseConfig } from "@repo/eslint-config";
export default [
  ...baseConfig,                          // umumiy qoidalar
  { rules: { "react/jsx-key": "error" } } // web-ga xos (React)
];

// apps/api/eslint.config.js:
import { baseConfig } from "@repo/eslint-config";
export default [...baseConfig];           // backend — faqat umumiy

Bu nima qiladi: Bu — umumiy config paketi (ESLint/tsconfig ulashish — 2.7, 15.3). packages/eslint-config — umumiy ESLint konfiguratsiya paketi: index.jsda baseConfig (recommended + TypeScript + maxsus qoidalar + Prettier — 15.3: Misol 2 — bir joyda). Ishlatish: apps/web/eslint.config.jsimport { baseConfig } from "@repo/eslint-config" + [...baseConfig, {React qoidalari}] (umumiy + web-ga xos — React); apps/api/eslint.config.js[...baseConfig] (faqat umumiy — backend React kerak emas). Nima qiladi: ESLint sozlamasi bir manba (packages/eslint-config) — barcha app ishlatadi (web, api, mobile). Agar qoida o'zgarsa (masalan yangi qoida qo'shish) — packages/eslint-configda bir joyda o'zgartiriladi barcha app avtomatik yangi qoidani oladi (izchillik). Nega bu muhim (15.3 + monorepo): (1) izchillik — barcha app bir xil ESLint qoidalari (har app o'zicha emas — chalkash bo'lmaydi — bir standart); (2) DRY (15.1 — bir konfiguratsiya — har app'da nusxa emas); (3) oson boshqaruv (qoida o'zgarsa — bir joy — hamma app'ga tarqaladi). Bu monorepo'ning yana bir afzalligi (2.4 — umumiy kod — bu yerda umumiy konfiguratsiya). Polyrepo'da har repo o'z ESLint config (nusxa — sinxronlashmaydi — har repo boshqacha). Monorepo + umumiy config — bir standart (izchil). Xuddi shunday packages/typescript-config (umumiy tsconfig.json — barcha app bir TypeScript sozlama), packages/prettier-config (umumiy Prettier). Bu — monorepo + 15.3 (kod sifati)ning birikmasi (umumiy config — barcha app bir xil sifat standarti — avtomatik, izchil). Bir marta sozlansa (packages/config) — barcha app foydalanadi (yangi app ham — import baseConfig — darrov standart). Bu — monorepo'ning kod sifati izchilligi (umumiy config paketlar).

Misol 5 — Monorepo vs polyrepo qarori (2.1, 2.7)

Maqsad: Aniq loyiha uchun monorepo yoki polyrepo tanlashni tahlil qilish. Bu arxitektura qarori (bir to'g'ri javob yo'q).

text
HOLAT 1: SaaS ilova (web + mobil + API + admin)
 Umumiy kod KO'P: tiplar, validatsiya, API client, UI komponentlar
 Atomik o'zgarish: API maydoni qo'shilsa — web+mobil+api birga
 MONOREPO (umumiy kod, izchillik, atomik o'zgarish)
   apps/{web,mobile,api,admin} + packages/{types,validation,ui,api-client}

HOLAT 2: Mustaqil mahsulotlar (blog platformasi + alohida CRM)
 Umumiy kod KAM (har biri alohida domen, jamoa, deploy)
 Atomik o'zgarish kerak emas (mustaqil rivojlanadi)
 POLYREPO (mustaqillik — har biri alohida repo)

HOLAT 3: Bitta Next.js ilova (kichik)
 Umumiy kod yo'q (bitta ilova)
 ODDIY REPO (monorepo ortiqcha — YAGNI — 15.1)

QAROR SAVOLLARI:
1. Ko'p loyiha umumiy kod ulashadimi? HA  monorepo
2. Atomik o'zgarish kerakmi (loyihalar birga)? HA  monorepo
3. Mustaqil (alohida jamoa/deploy)? HA  polyrepo
4. Bitta kichik ilova?  oddiy repo

Bu nima qiladi: Bu — monorepo vs polyrepo qarori (arxitektura tanlovi — bir to'g'ri javob yo'q — 2.1, 2.7). Uch holatda tahlil: Holat 1 (SaaS — web + mobil + API + admin): umumiy kod ko'p (tiplar, validatsiya, API client, UI — hamma loyiha ishlatadi), atomik o'zgarish kerak (API maydoni qo'shilsa — web + mobil + api birga o'zgaradi — izchil) monorepo (umumiy kod, izchillik, atomik o'zgarish — apps/{web,mobile,api,admin} + packages/{types,validation,ui,api-client}). Holat 2 (mustaqil mahsulotlar — blog + alohida CRM): umumiy kod kam (har biri alohida domen, jamoa, deploy — bog'liq emas), atomik o'zgarish kerak emas (mustaqil rivojlanadi) polyrepo (mustaqillik — har biri alohida repo — monorepo ortiqcha bog'lanish). Holat 3 (bitta kichik Next.js ilova): umumiy kod yo'q (bitta ilova) oddiy repo (monorepo ortiqcha murakkablik — YAGNI — 15.1: 2.1 — kerakmasini qilma). Qaror savollari: (1) ko'p loyiha umumiy kod ulashadimi? — ha monorepo; (2) atomik o'zgarish kerakmi (loyihalar birga)? — ha monorepo; (3) mustaqil (alohida jamoa/deploy)? — ha polyrepo; (4) bitta kichik ilova? oddiy repo. Nega bu muhim: monorepo kuchli, lekin har loyiha uchun emas 2.7-bob — noto'g'ri tanlov (kichik loyihaga monorepo — ortiqcha murakkablik; ko'p umumiy kodli loyihaga polyrepo — umumiy kod azob). To'g'ri tanlov — umumiy kod va bog'liqlikga qarab (umumiy kod ko'p + atomik o'zgarish monorepo; mustaqil polyrepo; bitta kichik oddiy repo). Bu — professional arxitektura qarori (texnologiyani tanlash — 13.11: 2.4 kabi — kontekstga mos, bir to'g'ri javob yo'q). Eng keng xato — "monorepo zamonaviy, ishlatamiz" (kichik loyihaga — ortiqcha) yoki "polyrepo oddiy" (ko'p umumiy kodli — umumiy kod azob). To'g'ri — loyiha strukturasini tahlil (umumiy kod, bog'liqlik, jamoa) mos tanlov. Ko'p kompaniya monorepo (umumiy kod, izchillik — katta loyiha), lekin kichik/mustaqil — oddiy repo/polyrepo. Bu — monorepo'ni qachon ishlatishni bilish (texnologiya emas — qaror).

Misol 6 — Real full-stack: Next.js web + NestJS api + shared paket (2.2–2.13)

Maqsad: To'liq monorepo — Next.js frontend, NestJS backend, umumiy tip/validatsiya paketi — CI va deploy bilan. Bu bobning barcha qismini birlashtiradi.

text
# Struktura:
my-app/
├── apps/
│   ├── web/          # Next.js (import @acme/validation, @acme/types)
│   └── api/          # NestJS (import @acme/validation, @acme/types)
├── packages/
│   ├── validation/   # Zod sxemalar (frontend + backend BIR manba)
│   ├── types/        # umumiy TypeScript tiplar
│   └── config/       # ESLint/tsconfig
├── pnpm-workspace.yaml
├── turbo.json
└── package.json
json
// apps/web/package.json va apps/api/package.json ikkalasida:
{
  "dependencies": {
    "@acme/validation": "workspace:*",   // local shared paket
    "@acme/types": "workspace:*"
  }
}
json
// turbo.json — web (Next) va api (Nest) build tartibi + kesh:
{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**"]   // Nest  dist, Next  .next
    },
    "dev": { "cache": false, "persistent": true },
    "lint": {},
    "test": { "dependsOn": ["^build"] }
  }
}
yaml
# .github/workflows/ci.yml — faqat o'zgargan (affected) + remote cache:
jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }          # git tarix (affected uchun)
      - run: pnpm install --frozen-lockfile
      - run: pnpm turbo run lint test build --filter='[origin/main]'
        env:
          TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}   # remote cache
          TURBO_TEAM: ${{ vars.TURBO_TEAM }}
dockerfile
# apps/api — Docker (turbo prune bilan minimal image):
# 1-bosqich: minimal subset
FROM node:20-alpine AS pruner
WORKDIR /app
RUN npm i -g turbo
COPY . .
RUN turbo prune api --docker            # faqat api + dependency'lari

# 2-bosqich: build (faqat kerakli qism)
FROM node:20-alpine AS builder
WORKDIR /app
RUN npm i -g pnpm
COPY --from=pruner /app/out/json/ .
RUN pnpm install --frozen-lockfile
COPY --from=pruner /app/out/full/ .
RUN pnpm turbo build --filter=api
CMD ["node", "apps/api/dist/main.js"]

Bu nima qiladi: Bu — real full-stack monorepo (bobning barcha qismi birga — 2.2–2.13). Struktura: apps/web (Next.js — 13-QISM) va apps/api (NestJS — 8-QISM) — ikkalasi packages/validation (Zod — bir manba) va packages/typesni ishlatadi (@acme/* — bu loyiha prefiksi). Bog'lanish: har app package.jsonida "@acme/validation": "workspace:*" (local — 2.3, 2.8) — frontend va backend bir validatsiyani ishlatadi (2.4 — o'zgartirsa ikkalasi to'g'ri). turbo.json (2.5, 2.9): build^build (bog'liq paketlar avval — validation/types build, keyin web/api), outputs — Nest dist, Next .next (kesh saqlaydi); dev — keshsiz, persistent (ikki dev server birga — turbo dev). CI 2.13-bob: --filter='[origin/main]' (faqat o'zgargan paketlar — agar faqat web o'zgarsa, api build qilinmaydi) + TURBO_TOKEN/TURBO_TEAM (remote cache — birov build qilgan CI keshdan — tez); fetch-depth: 0 (git tarix — affected uchun kerak). Docker (2.13, 2.9): turbo prune api --docker (faqat api + dependency'lari — web yo'q — minimal image — kichik, tez), ikki bosqichli build (avval json — lockfile bilan install, keyin to'liq kod — Docker layer keshini yaxshi ishlatadi). Nima qiladi: bir repo ikki mustaqil deploy (web Vercel — Root apps/web; api Docker/konteyner) + umumiy kod (validation/types — bir manba) + tez CI (affected + kesh). Nega bu kuchli: (1) umumiy kod — API tip va validatsiya frontend'da ham to'g'ri (end-to-end type safety — 2.4); (2) atomik o'zgarish — API maydoni qo'shilsa, types/validation + web + api bir PRda (izchil — 2.1); (3) tez CI — faqat o'zgargan + remote cache 2.13-bob; (4) moslashuvchan deploy — har app o'z target'i (Vercel web uchun optimallashgan, Docker api uchun — 2.13). Bu — bobning yakuniy amaliy natijasi (nazariyaning barchasi bir loyihada — struktura, workspace, shared, Turbo, CI, deploy). Real kompaniyalarda full-stack monorepo aynan shunday (Next + Nest/Express + shared — Turborepo yoki Nx bilan).


5. To'g'ri va noto'g'ri holatlar

1) Tashkil

text
 ko'p umumiy kod, polyrepo (nusxa/sinxron azob — 2.1)
 monorepo (umumiy kod bir joyda — Misol 5)

2) Struktura

text
 aralash (apps/packages ajratilmagan)
 apps (ilova) + packages (umumiy — 2.2)

3) Umumiy kod

text
 validatsiya nusxa (frontend+backend alohida — nomutanosiblik)
 shared paket (bir manba — Misol 2)

4) Build

text
 butun loyiha har marta (sekin — 2.5)
 Turborepo (kesh, faqat o'zgargan — Misol 3)

5) Config

text
 har app o'z ESLint (chalkash)
 umumiy config paket (izchil — Misol 4)

6) Qachon

text
 kichik ilovaga monorepo (ortiqcha — 2.7)
 ko'p loyiha+umumiy kod  monorepo (Misol 5)

7) Paket menejeri

text
 npm/yarn hoisting — phantom dependency (deploy'da sinadi — 2.8)
 pnpm (izolyatsiya — phantom bloklanadi, disk tejaydi)

8) CI

text
 har push'da butun monorepo build (sekin — 2.13)
 affected/filter + remote cache (faqat o'zgargan, kesh — Misol 6)

9) Deploy

text
 butun monorepo Docker image (og'ir, sekin — 2.13)
 turbo prune api --docker (minimal subset — Misol 6)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Kichik loyihaga monorepo

Sababi: "zamonaviy" deb 2.7-bob. Yechimi: oddiy repo (umumiy kod kam — Misol 5).

Xato 2 — Sekin build

Sababi: Turborepo/Nx yo'q 2.5-bob. Yechimi: build kesh (Misol 3).

Xato 3 — Umumiy kod nusxa

Sababi: shared paket yo'q 2.4-bob. Yechimi: packages/ shared (Misol 2).

Xato 4 — Aylanma bog'liqlik

Sababi: ui utils ui 2.7-bob. Yechimi: aniq, bir yo'nalishli bog'liqlik.

Xato 5 — Har app o'z config

Sababi: umumiy config yo'q 15.3-bob. Yechimi: packages/config (Misol 4).

Xato 6 — Workspace noto'g'ri

Sababi: paket bog'lanmagan 2.3-bob. Yechimi: workspace:* + pnpm-workspace.yaml.

Xato 7 — Phantom dependency

Sababi: npm/yarn hoisting — e'lon qilinmagan paket ishlatilgan 2.8-bob. Yechimi: pnpm (izolyatsiya) yoki har paket o'z dependency'sini e'lon qiladi.

Xato 8 — Kesh outputs noto'g'ri

Sababi: turbo.jsonda outputs yoki env to'liq emas — kesh eski/noto'g'ri natija beradi 2.9-bob. Yechimi: outputs (barcha build natijasi) + envni to'g'ri e'lon qilish.

Xato 9 — Ichki paketni versiyalash

Sababi: faqat workspace:* bilan ishlatiladigan paketga Changesets qo'shish (2.11 — ortiqcha). Yechimi: versiyalash faqat npm'ga nashr qilinadigan paketlar uchun.


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Linter 15.3-bob: umumiy ESLint/Prettier config (packages/config).
  • TypeScript (7-QISM): umumiy tiplar, tsconfig (shared).
  • Validatsiya (13.5, 11.10): umumiy Zod (frontend+backend).
  • Next.js (13-QISM): apps/web (monorepo'da — Vercel deploy — 2.13).
  • NestJS (8-QISM): apps/api (Docker + turbo prune — 2.13).
  • CI/CD (10.9, 10.5): faqat o'zgargan (affected/filter) + remote cache + matrix — tez 2.13-bob.
  • Docker (14-QISM): turbo prune — minimal image (2.9, 2.13).
  • Toza kod 15.1-bob: DRY — monorepo umumiy kod; YAGNI — kichik oddiy repo.

8. Eng yaxshi amaliyotlar (best practices)

  • apps/packages ajrat (ilova vs umumiy — 2.2).
  • Workspace (pnpm) (tez, disk tejaydi, phantom bloklaydi — 2.3, 2.8).
  • Shared paket (validatsiya/tip — bir manba — Misol 2).
  • Turborepo/Nx (build kesh — Misol 3; remote cache jamoa/CI — 2.9).
  • Umumiy config (ESLint/tsconfig — Misol 4).
  • Aniq bog'liqlik (bir yo'nalishli — aylanma yo'q — 2.7).
  • Qachon monorepo (umumiy kod ko'p — Misol 5).
  • Boshlang'ich Turborepo (oson — Nx keyin — 2.6, 2.10).
  • Affected CI (filter + remote cache — faqat o'zgargan — 2.13).
  • Deploy — har app alohida (Vercel web, Docker+prune api — 2.13, Misol 6).
  • Versiyalash faqat nashr uchun (Changesets — ichki paketga emas — 2.11).
  • YAGNI (kichik oddiy repo — 15.1).

9. Amaliy loyiha: "Full-Stack Monorepo"

Monorepo qurishni mustahkamlash.

Maqsad

Full-stack monorepo qur — web (Next.js) + api (NestJS/Express) + umumiy paketlar.

Talablar (requirements)

  1. Struktura: apps (web, api) + packages (Misol 1).
  2. Workspace: pnpm-workspace 2.3-bob.
  3. Turborepo: create-turbo (Misol 1).
  4. Shared validatsiya: Zod (frontend+backend — Misol 2).
  5. Shared types: umumiy TypeScript tiplar 2.4-bob.
  6. Umumiy config: ESLint/tsconfig (Misol 4).
  7. Pipeline: turbo.json (build tartibi/kesh — Misol 3).
  8. Build kesh: o'zgarmagan keshdan (Misol 3).
  9. Aniq bog'liqlik: apppackage (aylanma yo'q — 2.7).
  10. Qaror: monorepo nega (umumiy kod — Misol 5).

Maslahatlar (hint)

  • create-turbo (oson boshlash — Misol 1).
  • Shared paket (umumiy kod — Misol 2).
  • Umumiy config (Misol 4).
  • Build kesh (Xato 2).
  • Aniq bog'liqlik (Xato 4).

"Tayyor" mezonlari (acceptance criteria)

  • apps + packages struktura.
  • Workspace (bog'langan).
  • Shared validatsiya (frontend+backend).
  • Umumiy config.
  • Turborepo kesh (tez build).
  • Aniq bog'liqlik.

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda monorepo (Turborepo/Nx)'ni chuqur o'rgandik:

  • Monorepo vs polyrepo 2.1-bob; struktura (apps/packages — 2.2); workspace 2.3-bob va uning ichki ishlashi (hoisting, phantom, pnpm — 2.8); umumiy kod (shared — 2.4); Turborepo (kesh — 2.5) va chuqur (remote cache, filter, prune — 2.9); Nx 2.6-bob va chuqur (generator, executor, affected, integrated/package-based — 2.10); versiyalash (Changesets — 2.11); TypeScript monorepo (paths, project references — 2.12); CI va deploy (affected, remote cache, Vercel, Docker+prune — 2.13); best practices/qachon 2.7-bob.

Endi siz ko'p loyihani bir joyda boshqara olasiz: monorepo (umumiy kod, izchillik), Turborepo (tez build), shared paketlar (validatsiya/tip — bir manba). Va monorepo qachon kerakligini bilasiz (umumiy kod ko'p — ha; mustaqil — polyrepo).

Keyingi bob — 15.5-bob: Debugging metodologiyasi. Monorepo'ni bildik; endi muhim amaliy ko'nikma — debugging (xatolarni topish va tuzatish)ni ko'ramiz: tizimli yondashuv (taxmin emas — usul), vositalar (debugger, breakpoint, DevTools), texnikalar (binary search, log, rubber duck), va keng xato turlari. Bu — har dasturchi kunlik ishida ishlatadigan eng muhim ko'nikmalardan.


Foydalanilgan rasmiy/ishonchli manbalar

  • Turborepo rasmiy hujjati — pipeline (turbo.json, dependsOn, outputs), caching (local/remote), --filter, turbo prune, create-turbo.
  • Nx rasmiy hujjati — generators, executors, nx affected, project graph, plugins, integrated vs package-based, Nx Cloud (remote cache, distributed task execution).
  • pnpm workspaces hujjatipnpm-workspace.yaml, workspace: protocol, izolyatsiyalangan node_modules, content-addressable store.
  • npm/yarn workspaces hujjatipackage.json workspaces, hoisting va phantom dependency.
  • Changesets hujjatichangeset, changeset version, changeset publish, fixed vs independent versioning.
  • TypeScript hujjati — project references (composite, tsc --build), path mapping (paths).
  • Vercel monorepo qo'llanmasi — Next.js app'ni monorepo'dan deploy qilish (Root Directory, Build Command).

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
15.4-bob: Monorepo (Turborepo / Nx) — Wisar