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) monorepo — barcha 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
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/NxMonorepo 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/ichidaapps/(ilovalar — web, mobile, api) vapackages/(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
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 joydaMonorepo strukturasi — apps va packages tashkili. Monorepo ikki asosiy qismdan iborat:
apps/(ilovalar — deploy qilinadigan — masalanweb— Next.js,mobile— React Native,api— NestJS) vapackages/(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/): masalanvalidationpaketidaUserSchema(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)
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/vaapps/ni "paketlar" deb taniydi (har papka — alohida paket — o'zpackage.jsoni bilan); (2)@repo/uini local paket sifatida bog'laydi (npm registry'dan emas — local papka'dan —packages/ui— to'g'ridan); (3) bir martanpm install(root'da) — barcha paketning bog'lanishi (apps shared paketlarga ulanadi). pnpm workspace (eng tez, samarali — disk tejaydi — tavsiya):pnpm-workspace.yaml—packages: ["apps/*", "packages/*"](qaysi papkalar workspace). Rootpackage.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). Birinstall— butun monorepo bog'langan (apps shared paketlarni ishlatadi).
2.4. Umumiy kod (shared paketlar)
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.tsdaUserSchema(Zod — email, name) +Usertip (z.infer). Ishlatish (ikki joyda — bir manba):apps/web(frontend — forma validatsiya — RHF+Zod — 11.10)import { UserSchema } from "@repo/validation", vaapps/api(backend — API validatsiya — 13.5: 2.9) xuddi shuimport { UserSchema } from "@repo/validation"— bir sxema, ikki joyda. Natija: agar validatsiya o'zgarsa (masalannamemin 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 — frontendmin 2, backendmin 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)
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 — masalanuipaketni build, keyin uni ishlatadiganweb— 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
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 NxNx 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 generatebilan 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
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'liqlikMonorepo 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 —uiutilsui— 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
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 rootnode_modulesga ko'tariladi (hoist qilinadi — flat struktura — bir joyda). Buning yon ta'siri — phantom dependency:apps/webo'zpackage.jsonidazodni e'lon qilmasa ham, boshqa paket (masalanpackages/validation) uni root'ga hoist qilgani uchun,apps/webdaimport { z } from "zod"ishlab ketadi — lekin bu xavfli:webni yakka deploy qilganda (faqatapps/web— root'siz — masalan Docker'da bitta app)zodtopilmaydi build sinadi; yokivalidationzoddan voz kechsa —websababsiz sinadi. pnpm buni hal qiladi: symlink asosli, izolyatsiyalangannode_modules(har paket faqat o'zpackage.jsonidagi dependency'ni ko'radi — qat'iy); haqiqiy fayllarnode_modules/.pnpmstore'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, lekinnpm 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
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 subsetTurborepo 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 uchunturbo.jsondaoutputs(kesh nima saqlaydi —dist/**) vainputs/envto'g'ri bo'lishi muhim (aks holda kesh noto'g'ri ishlaydi — masalanenvo'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]'(mainbranch'dan beri git'da o'zgargan paketlar — CI'da eng keng). Prune (deploy uchun):turbo prune web --dockerfaqatwebva 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
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'zpackage.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)
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 —patchtuzatish,minoryangi imkoniyat,majorbuzuvchi o'zgarish) va izohni kiritish.changeset/*.mdfayl yaratadi (PR bilan birga commit — o'zgarish "niyati" saqlanadi); (2)npx changeset version— yig'ilgan changeset'larni hisobga olib paket versiyalarini ko'taradi vaCHANGELOG.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 (ichkiapps/deploy qilinadi — versiyalanmaydi).
2.12. TypeScript monorepo — project references va path
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 tartibiniTypeScript monorepo — umumiy tiplarni ulashning ikki yondashuvi. 1) Path mapping (sodda — eng keng):
tsconfig.base.jsonda"paths": { "@repo/*": ["packages/*/src"] }—@repo/uiimporti to'g'ridanpackages/ui/srcga xaritalanadi (build kerak emas — TypeScript source'ni to'g'ridan o'qiydi — dev'da tez,create-turboshu 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" }](webuiga 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 (.tsbuildinfobilan). 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 uchunpathsyetadi (create-turbodefault), project references keyin (loyiha juda o'sganda).
2.13. CI va deploy — affected/matrix va har app alohida
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 targetCI 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/webVercel (Root Directory:apps/web, Build Command:turbo build --filter=web— Vercel monorepo'ni tushunadi);apps/apiDocker: avvalturbo prune api --docker(faqatapi+ 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
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 polyrepo4. 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.
# 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# pnpm-workspace.yaml:
packages:
- "apps/*"
- "packages/*"// 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).
// packages/validation/package.json:
{
"name": "@repo/validation",
"version": "0.0.0",
"main": "./src/index.ts",
"types": "./src/index.ts",
"dependencies": { "zod": "^3.23.0" }
}// 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>;// 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.
// 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
}
}
}# 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): 8sBu nima qiladi: Bu — Turborepo pipeline (build tartibi va kesh — 2.5). turbo.json — task'lar pipeline (qaysi task qanday ishlaydi): (1) build — "dependsOn": ["^build"] (^build — bog'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).
// packages/eslint-config/package.json:
{
"name": "@repo/eslint-config",
"version": "0.0.0",
"main": "index.js"
}// 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,
];// 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 umumiyBu 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.js — import { 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).
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 repoBu 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.
# 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// apps/web/package.json va apps/api/package.json ikkalasida:
{
"dependencies": {
"@acme/validation": "workspace:*", // local shared paket
"@acme/types": "workspace:*"
}
}// 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"] }
}
}# .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 }}# 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
ko'p umumiy kod, polyrepo (nusxa/sinxron azob — 2.1)
monorepo (umumiy kod bir joyda — Misol 5)2) Struktura
aralash (apps/packages ajratilmagan)
apps (ilova) + packages (umumiy — 2.2)3) Umumiy kod
validatsiya nusxa (frontend+backend alohida — nomutanosiblik)
shared paket (bir manba — Misol 2)4) Build
butun loyiha har marta (sekin — 2.5)
Turborepo (kesh, faqat o'zgargan — Misol 3)5) Config
har app o'z ESLint (chalkash)
umumiy config paket (izchil — Misol 4)6) Qachon
kichik ilovaga monorepo (ortiqcha — 2.7)
ko'p loyiha+umumiy kod monorepo (Misol 5)7) Paket menejeri
npm/yarn hoisting — phantom dependency (deploy'da sinadi — 2.8)
pnpm (izolyatsiya — phantom bloklanadi, disk tejaydi)8) CI
har push'da butun monorepo build (sekin — 2.13)
affected/filter + remote cache (faqat o'zgargan, kesh — Misol 6)9) Deploy
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)
- Struktura: apps (web, api) + packages (Misol 1).
- Workspace: pnpm-workspace 2.3-bob.
- Turborepo: create-turbo (Misol 1).
- Shared validatsiya: Zod (frontend+backend — Misol 2).
- Shared types: umumiy TypeScript tiplar 2.4-bob.
- Umumiy config: ESLint/tsconfig (Misol 4).
- Pipeline: turbo.json (build tartibi/kesh — Misol 3).
- Build kesh: o'zgarmagan keshdan (Misol 3).
- Aniq bog'liqlik: apppackage (aylanma yo'q — 2.7).
- 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 hujjati —
pnpm-workspace.yaml,workspace:protocol, izolyatsiyalangannode_modules, content-addressable store. - npm/yarn workspaces hujjati —
package.jsonworkspaces, hoisting va phantom dependency. - Changesets hujjati —
changeset,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!