Mundarija (39)
- Bu darsda
- 1. Nega bu kerak?
- 2. nest new — loyiha yaratish
- 2.1 Buyruq
- 2.2 Chiqish
- 2.3 Fayllar xaritasi
- 3. Fayllar ichida nima bor
- 3.1 package.json — ESM va skriptlar
- 3.2 tsconfig.json — dekorator bayroqlari
- 3.3 main.ts — kirish nuqtasi
- 3.4 nest-cli.json
- 4. Build: nega kerak va qanday ishlaydi
- 4.1 node fayl.ts nega ishlamaydi
- 4.2 nest build nima qiladi
- 4.3 nest start --watch
- 4.4 Builder'lar: tsc, SWC, webpack, Rspack
- 5. Test va lint
- 5.1 Vitest
- 5.2 oxlint va Prettier
- 6. Generatorlar: nest g
- 6.1 nest g resource
- 6.2 Generator tuzoqlari
- 6.3 Boshqa generatorlar
- 7. Papka tuzilmasi
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): qaysi fayl?
- 2-mashq (o'rta): import kengaytmasini almashtirish
- 3-mashq (qiyin): o'z demo loyihangiz
- 10. Loyiha qadami: Nest skeleti vazifalar-api da
- 10.1 Reja
- 10.2 tsconfig.json
- 10.3 Build fayllari
- 10.4 Kod: modul, controller, kirish nuqtasi
- 10.5 Test va skriptlar
- 10.6 Tekshiruv va commit
- 11. Real ishda
- Xulosa
- Manbalar
Nest CLI va loyiha tuzilmasi: nest new, nest build va NestJS 12 vositalari
Qisqacha:
nest newbir buyruq bilan tayyor Nest loyihasini yaratadi: 17 fayl, ESM ("type": "module"), Vitest testlari, oxlint va Prettier.nest g resourcemodul, controller, xizmat va DTO fayllarini yasab, ildiz modulga o'zi ulaydi. Nest kodi dekorator metama'lumoti tufayli build talab qiladi:nest build(sukut —tsc)src/dandist/ga JS yozadi, servernode dist/main.jsbilan ishga tushadi. 25-qismdagi "build yo'q" qarori shu darsda tugaydi.
Bu darsda
nest newbilan loyiha yaratib, har faylning vazifasini aytib bera olasiz.nest buildnima qilishini va nega Nest kodininode fayl.tsbilan yurgizib bo'lmasligini tushuntirasiz.- Builder'larni (tsc, SWC, webpack, Rspack) va ESM/CommonJS tanlovini farqlaysiz.
nest g resourceva boshqa generatorlar bilan fayl yasaysiz, ularning tuzoqlarini bilasiz.vazifalar-apiga Nest skeletini qo'shib, birinchi commit qilasiz.
Oldin bilishingiz kerak: NestJS nima va nega, TypeScript'ni Node'da to'g'ridan ishga tushirish, Express + TypeScript, Vitest I, Biome va Oxlint.
O'tgan darsda Nest paketlarini vazifalar-api ga o'rnatdik. Endi ularni ishga solamiz. Avval toza loyihada Nest qanday tuzilishini ko'ramiz, keyin xuddi shu tuzilmani bizning loyihaga olib kiramiz.
1. Nega bu kerak?
Express loyihasini qanday boshlagandik? npm init, npm i express, tsconfig.json ni qo'lda yozish, test vositasini tanlash, lint sozlash (Express + TypeScript). Har qadam — alohida qaror.
Nest'da bu qarorlar oldindan qilingan. CLI (command line interface — buyruq qatori vositasi) nest bitta buyruq bilan hammasini yasaydi. U faqat loyiha yaratmaydi: build qiladi, serverni kuzatib qayta ishga tushiradi, yangi modul va controller fayllarini shablondan yasaydi.
O'xshatish: Express — oshxonada noldan ovqat qilish. Nest CLI — yarim tayyor mahsulot to'plami: hamma masalliq o'lchangan, retsept ichida. Tez boshlaysiz, lekin to'plamda nima borligini bilishingiz kerak — aks holda keraksiz narsa ham qozonga tushadi.
2. nest new — loyiha yaratish
2.1 Buyruq
CLI'ni global o'rnatish shart emas — npx yetadi:
npx @nestjs/cli@12.0.9 new demo --skip-git --skip-install \
-p npm --no-observe| Bayroq | Ma'nosi |
|---|---|
--skip-git |
git init qilmasin |
--skip-install |
npm install ni keyin o'zimiz qilamiz |
-p npm |
paket menejeri (so'ramasin) |
--no-observe |
NestJS Observe xizmatini ulashni so'ramasin |
Bayroqlarsiz CLI bir nechta savol beradi. Nest 12 hujjati yana bitta savolni aytadi: CommonJS yoki ESM. Bizning yugurishda (bayroqlar bilan) savol chiqmadi va CLI ESM loyiha yaratdi. Kanonda ham aynan shunday bo'lgan.
2.2 Chiqish
Biz ishga tushirdik (CLI 12.0.9, Node 24.21.0) — chiqish kanonnikidan farq qilmadi:
CREATE demo/.gitattributes (20 bytes)
CREATE demo/.oxlintrc.json (216 bytes)
CREATE demo/.prettierrc (56 bytes)
CREATE demo/AGENTS.md (1235 bytes)
CREATE demo/nest-cli.json (179 bytes)
CREATE demo/README.md (7607 bytes)
CREATE demo/tsconfig.build.json (178 bytes)
CREATE demo/tsconfig.json (624 bytes)
CREATE demo/vitest.config.e2e.ts (212 bytes)
CREATE demo/vitest.config.ts (361 bytes)
CREATE demo/package.json (1457 bytes)
CREATE demo/src/app.controller.ts (289 bytes)
CREATE demo/src/app.module.ts (265 bytes)
CREATE demo/src/app.service.ts (150 bytes)
CREATE demo/src/main.ts (245 bytes)
CREATE demo/src/app.controller.spec.ts (645 bytes)
CREATE demo/test/app.e2e-spec.ts (760 bytes)17 fayl, kanonda 2.8 soniya. Keyin npm install — 335 paket, node_modules 162 MB (kanon 41.7 s, bizda tarmoq sekin bo'lgani uchun 1.5 daqiqa).
2.3 Fayllar xaritasi
demo/
├── src/ ilova kodi
│ ├── main.ts kirish nuqtasi
│ ├── app.module.ts ildiz modul
│ ├── app.controller.ts GET / marshruti
│ ├── app.service.ts "Hello World!" qaytaradi
│ └── app.controller.spec.ts unit test
├── test/app.e2e-spec.ts HTTP orqali test
├── nest-cli.json CLI sozlamasi
├── tsconfig.json TypeScript sozlamasi
├── tsconfig.build.json build uchun qo'shimcha
├── vitest.config.ts unit testlar
├── vitest.config.e2e.ts e2e testlar
├── .oxlintrc.json lint qoidalari
└── .prettierrc formatlashTest fayl qayerda turishiga qarang: unit test (*.spec.ts) — tekshirayotgan fayli yonida, src/ ichida. E2e test — alohida test/ papkada. Bu — Nest odati.
3. Fayllar ichida nima bor
3.1 package.json — ESM va skriptlar
Eng muhim qator — "type": "module". NestJS 12 loyihasi ESM (ES Modules Node'da). 11-versiyagacha nest new CommonJS loyiha yaratardi; internetdagi ko'p misollarda require va "module": "commonjs" ni shuning uchun ko'rasiz.
Nest 12 paketlarining o'zi faqat ESM. CommonJS ilova ularni require(esm) orqali yuklaydi — bu Node 20.19 va 22.12 dan boshlab bayroqsiz ishlaydi (CJS va ESM birga). Hujjat bo'yicha CommonJS loyiha Jest bilan, ESM loyiha Vitest bilan yaratiladi. Biz ESM'da qolamiz — vazifalar-api 25-qismdan beri ESM.
Skriptlar:
| Skript | Buyruq | Nima qiladi |
|---|---|---|
build |
nest build |
src/ → dist/ |
start:dev |
nest start --watch |
build + ishga tushirish + kuzatish |
start:prod |
node dist/main |
tayyor build'ni yurgizish |
test |
vitest run |
unit testlar |
test:e2e |
vitest run --config ./vitest.config.e2e.ts |
e2e testlar |
lint |
oxlint --type-aware src/ test/ |
lint |
Yana ikkita narsa bor, ular ixtiyoriy. "deploy": "nest deploy" skripti va @nestjs/mau dev paketi — Nest jamoasining pullik deploy xizmati uchun. AGENTS.md fayli esa AI yordamchilar uchun yozilgan va NestJS Observe (yana pullik xizmat) reklamasini qiladi. Bular loyihaning ishlashiga ta'sir qilmaydi — o'chirib yuborsangiz bo'ladi.
Versiyalarga ham qarang: "@nestjs/core": "^12.0.1". Belgi ^ — "12.x ning eng yangisi" (semver). Shuning uchun bugun o'rnatsangiz 12.3 tushadi. Kanon 12.2.0 ni --save-exact bilan qotirdi.
3.2 tsconfig.json — dekorator bayroqlari
{
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "ES2023",
"outDir": "./dist",
"strict": true,
"strictPropertyInitialization": false,
"types": ["vitest/globals", "node"]
}
}Bu — 20 qatorlik faylning eng muhim qismi (to'liq faylda yana declaration, sourceMap, incremental kabi build sozlamalari bor).
experimentalDecoratorsvaemitDecoratorMetadata— legacy dekoratorlar. Ularsiz@Controller()ham, DI ham ishlamaydi.nodenext— ESM qoidalari: nisbiy importda kengaytma majburiy. Shuning uchun shablondafrom './app.module.js'—.tsfayl, lekin.jsyozilgan. Build'dan keyin aynan.jsfayl bo'ladi.strictPropertyInitialization: false— klass maydoni constructor'da qiymat olmasa ham xato bermaydi. Nest buni DTO klasslari uchun o'chiradi.vitest/globals— testlardadescribe,it,expectni import qilmasdan ishlatish.
3.3 main.ts — kirish nuqtasi
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module.js';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(process.env.PORT ?? 3000);
}
await bootstrap();NestFactory.create(AppModule) — ildiz moduldan boshlab butun ilovani yig'adi: modullarni o'qiydi, provider'larni yaratadi, marshrutlarni Express'ga ulaydi. app.listen — 25-qismdagi server.listen ning o'zi. Oxirgi qator await bootstrap() — top-level await, faqat ESM'da ishlaydi. Bu faylni Bootstrap: main.ts darsida chuqur ko'ramiz.
app.module.ts, app.controller.ts, app.service.ts ni o'tgan darsda ko'rdik: modul controller va xizmatni ro'yxatga oladi, controller xizmatni constructor orqali oladi. Har biri — keyingi uch darsning mavzusi.
3.4 nest-cli.json
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}collection— generatorlar shablonlari qayerdan olinadi (@nestjs/schematicspaketi).sourceRoot— kod papkasi.deleteOutDir— har build'dan oldindist/ni tozalash. Aks holda o'chirilgan faylning eski JS nusxasidist/da qolib ketadi.
Bu yerga builder, tsConfigPath, entryFile kabi sozlamalar ham yoziladi — pastda ko'ramiz.
Tekshirib ko'ring: Shablondagi
import { AppModule } from './app.module.js'— lekin papkadaapp.module.jsyo'q, faqatapp.module.ts. Bu xato emasmi?
Javob
Xato emas. nodenext rejimida TypeScript import yo'lini build'dan keyingi holatga qarab yozishni talab qiladi: dist/ da app.module.js bo'ladi. TypeScript tekshiruvda .js ni ko'rib, yonidagi .ts faylni topadi. vazifalar-api da esa boshqa yo'l tanlanadi — .ts yoziladi va kompilyator uni .js ga almashtiradi. Buni «Loyiha qadami» bo'limida ko'ramiz.
4. Build: nega kerak va qanday ishlaydi
4.1 node fayl.ts nega ishlamaydi
25-qismdan beri vazifalar-api ni build'siz ishga tushirgandik: node src/server.ts. Node 24 turlarni o'chirib tashlaydi (type stripping). Express + TypeScript darsida o'lchab, "build yo'q" deb qaror qilgandik.
Nest kodi bilan bu yo'l yopiladi. Biz Nest skeleti qo'shilgan vazifalar-api ni eski usulda yurgizib ko'rdik (Node 24.21.0):
node src/main.tsfile:///C:/Users/…/vazifalar-api/src/app.module.ts:7
@Module({
^
SyntaxError: Invalid or unexpected tokenNode @ belgisida to'xtadi. Type stripping faqat turlarni o'chiradi, qolgan sintaksis haqiqiy JavaScript bo'lishi kerak. Dekoratorlar esa bugungi Node'da bajarilmaydi. Bundan tashqari, design:paramtypes metama'lumotini faqat kompilyator yoza oladi — type stripping uni yaratmaydi.
Ikkinchi to'siq — erasableSyntaxOnly. 25–27-qismda bu bayroq yoqiq edi: "faqat o'chiriladigan sintaksis". Nest'ning odatiy constructor yozuvi constructor(private readonly x: X) esa o'chirib bo'lmaydigan sintaksis — u this.x = x qatorini qo'shadi. Bayroqni demo loyihaga yoqib, tsc ni yurgizdik:
src/app.controller.ts(6,15): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.Tarjimasi: "erasableSyntaxOnly yoqilganda bu sintaksisga ruxsat yo'q." 6-qator, 15-ustun — aynan private readonly. Shuning uchun Nest loyihasida bu bayroq bo'lmaydi.
4.2 nest build nima qiladi
flowchart LR
S["src/*.ts"] --> B["nest build (tsc)"]
T["tsconfig.build.json"] --> B
B --> D["dist/*.js + .map + .d.ts"]
D --> N["node dist/main.js"]
S -. "type stripping: @ da SyntaxError" .-> X["node src/main.ts"]Diagrammaga qarang: yuqori yo'l ishlaydi, pastdagi punktir yo'l — yo'q. nest build sukut bo'yicha oddiy tsc ni chaqiradi (transpilyatsiya darsi), tsconfig.build.json bilan. U testlarni (*spec.ts, test/) build'ga qo'shmaydi.
Demo loyihada npm run build (biz ishga tushirdik, 4.3 s) dan keyin dist/ da 12 fayl: har .ts uchun .js, .js.map (manba xaritasi) va .d.ts (turlar). Kanonda: 3.5 s, 25 KB. dist/app.controller.js ning oxiri:
AppController = __decorate([
Controller(),
__metadata("design:paramtypes", [AppService])
], AppController);__metadata("design:paramtypes", [AppService]) — o'tgan darsdagi JS modelimizdagi [VazifalarXizmati] ning aynan o'zi. Nest DI shu qatorga tayanadi.
4.3 nest start --watch
Dasturlash paytida har safar build qilib, serverni qo'lda qayta yurgizish noqulay. npm run start:dev (nest start --watch) — tsc ni kuzatish rejimida ishga tushiradi va har saqlashda serverni qayta ko'taradi. Express'dagi node --watch (--watch darsi) ning Nest varianti, faqat orasida build bor.
4.4 Builder'lar: tsc, SWC, webpack, Rspack
nest build --help to'rt builder'ni sanaydi: tsc, webpack, swc, rspack. Tanlov — nest-cli.json da "compilerOptions": { "builder": "swc" } yoki --builder swc bayrog'i.
| Builder | Nima | Qachon |
|---|---|---|
tsc (sukut) |
TypeScript kompilyatori | hamma holat, eng ishonchli |
swc |
Rust'da yozilgan tez kompilyator | katta loyiha, build sekin bo'lsa |
webpack |
bitta faylga yig'uvchi | monorepo, maxsus holatlar |
rspack |
webpack'ning Rust'dagi tez muqobili | webpack o'rniga |
Kanon vazifalar-api ni (ko'chish tugagan holatda) ikki builder bilan o'lchadi: tsc 15.9–16.6 s, swc 4.6–5.4 s. SWC uch baravar tez. Lekin SWC build'i ishga tushmadi:
Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'C:\Users\…\dist\config.Sabab: vazifalar-api importlarda .ts kengaytma yozadi va tsc uni build'da .js ga almashtiradi. SWC bu almashtirishni qilmaydi — dist/ da config.ts ga import qolib ketdi. Shuning uchun kanon tsc da qoldi. Nest hujjati uslubida (.js importlar) SWC muammosiz ishlaydi. Webpack va Rspack builder'lari kanonda sinalmagan.
Diqqat: SWC build "exit 0" bilan tugadi — xato faqat ishga tushirganda chiqdi. Build muvaffaqiyati ilova ishlashini kafolatlamaydi. CI'da build'dan keyin ilovani bir marta ko'tarib, bitta so'rov yuborish — arzon va foydali tekshiruv.
5. Test va lint
5.1 Vitest
Nest 12 ESM loyihasining sukut test vositasi — Vitest (Vitest I). Ilgari Nest Jest ishlatardi. app.controller.spec.ts:
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller.js';
import { AppService } from './app.service.js';
describe('AppController', () => {
let appController: AppController;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [AppController],
providers: [AppService],
}).compile();
appController = app.get<AppController>(AppController);
});
describe('root', () => {
it('should return "Hello World!"', () => {
expect(appController.getHello()).toBe('Hello World!');
});
});
});Test.createTestingModule — test uchun kichik Nest ilovasi. U ham DI konteyner: app.get(AppController) tayyor, xizmati ulangan controller'ni beradi. Haqiqiy xizmat o'rniga soxtasini berish ham shu yerda (Mock, stub, spy va fake g'oyasi). Bu NestJS unit testlari darsining mavzusi.
Kanon chiqishi (npm test, Vitest 4.1.12 — shablon ^4.1.2 yozadi):
✓ src/app.controller.spec.ts (1 test) 599ms
✓ should return "Hello World!" 597ms
Test Files 1 passed (1)
Tests 1 passed (1)Bitta oddiy test 599 ms — DI konteynerni ko'tarish va dekoratorli fayllarni o'girish vaqti. Vitest dekorator metama'lumotini o'zi chiqaradi: Vite 8 tsconfig dagi emitDecoratorMetadata ni o'qiydi, alohida plagin kerak emas.
5.2 oxlint va Prettier
Lint — oxlint (Biome va Oxlint), ESLint emas. --type-aware — turlarga qarab tekshiradigan qoidalar ham ishlaydi (masalan, no-floating-promises — kutilmagan Promise). Toza loyihada kanon natijasi: Found 0 warnings and 0 errors. (11.8 s). Formatlash — Prettier, .prettierrc da bitta tirnoq va oxirgi vergul.
vazifalar-api da 25-qismdan beri ESLint (typescript-eslint strict) bor. Kanon uni almashtirmadi: ikkalasi bir ishni qiladi, almashtirish — alohida qaror.
6. Generatorlar: nest g
6.1 nest g resource
Yangi resurs uchun fayllarni qo'lda yozish shart emas. Demo loyihada mahsulotlar resursini yaratdik (biz ishga tushirdik):
npx nest g resource mahsulotlar --type rest --crudCREATE src/mahsulotlar/mahsulotlar.controller.ts (1073 bytes)
CREATE src/mahsulotlar/mahsulotlar.controller.spec.ts (652 bytes)
CREATE src/mahsulotlar/mahsulotlar.module.ts (305 bytes)
CREATE src/mahsulotlar/mahsulotlar.service.ts (737 bytes)
CREATE src/mahsulotlar/mahsulotlar.service.spec.ts (516 bytes)
CREATE src/mahsulotlar/dto/create-mahsulotlar.dto.ts (38 bytes)
CREATE src/mahsulotlar/dto/update-mahsulotlar.dto.ts (204 bytes)
CREATE src/mahsulotlar/entities/mahsulotlar.entity.ts (29 bytes)
UPDATE package.json (1434 bytes)
UPDATE src/app.module.ts (355 bytes)--type rest --crud bo'lmasa, CLI ikki savol beradi (qaysi transport, CRUD kerakmi). Natijada 8 ta yangi fayl va ikki UPDATE:
app.module.tsgaimports: [MahsulotlarModule]qo'shildi — yangi modul o'zi ulandi.package.jsonga"@nestjs/mapped-types": "*"qo'shildi va CLI uni o'rnatdi (DTO uchun kerak).
Generatsiya qilingan controller'dan parcha:
@Get(':id')
findOne(@Param('id') id: string) {
return this.mahsulotlarService.findOne(+id);
}Xizmat esa faqat satr qaytaradi: This action returns a #${id} mahsulotlar. Bu — skelet, mantiqni siz yozasiz. npm test uchala spec'ni o'tkazdi (3/3).
6.2 Generator tuzoqlari
Generatsiya qilingan kodni ko'r-ko'rona qabul qilmang. Biz topgan to'rtta joy:
"*"versiya.@nestjs/mapped-typesistalgan versiyaga ruxsat oldi. Bugun 12.0.0 tushdi, ertaga 13 tushib, loyihani buzishi mumkin. Aniq versiya yozing.- Inglizcha birlik shakl. CLI
create-mahsulotlar.dto.tsyasadi. U ko'plikni birlikka faqat inglizchada aylantiradi (users→CreateUserDto). O'zbekcha nomdaCreateMahsulotlarDto— qo'lda tuzating. +id."abc"kelsa+id—NaN, xato yo'q. Kirishni tekshirish kerak — Pipe'lar darsida.- Lint ogohlantirishlari.
oxlintxizmatdagi ishlatilmagan parametrlar uchun 2 ta ogohlantirish berdi:Parameter 'createMahsulotlarDto' is declared but never used.
6.3 Boshqa generatorlar
| Buyruq | Nima yasaydi |
|---|---|
nest g module vazifalar |
vazifalar/vazifalar.module.ts + AppModule'ga import |
nest g controller vazifalar |
controller + spec, modulga qo'shadi |
nest g service vazifalar |
xizmat + spec, modulga qo'shadi |
nest g guard, pipe, filter |
keyingi darslardagi g'ishtlar |
Foydali bayroqlar: --dry-run (-d) — faylga yozmasdan, nima qilishini ko'rsatadi; --no-spec — test faylsiz; --flat — alohida papka ochmaydi; --skip-import — modulga ulamaydi.
Maslahat: Notanish generatorni avval
--dry-runbilan yurgizing. U qaysi fayllarni yaratishi va qaysilarini o'zgartirishini ko'rsatadi — kutilmaganUPDATEni oldindan ko'rasiz.
7. Papka tuzilmasi
Nest feature-folder tuzilmasini kutadi: har modul — o'z papkasi. 25-qismda biz ham shunday qilgandik (qatlamlar darsi). Farq — fayl nomlari: Nest uslubida <mavzu>.<tur>.ts.
| 25–27 (Express) | 30 (Nest) |
|---|---|
src/server.ts |
src/main.ts |
src/ilova.ts |
src/app.module.ts + ilova.ts |
vazifalar/marshrut.ts |
vazifalar/vazifalar.controller.ts |
vazifalar/xizmat.ts |
vazifalar/vazifalar.service.ts |
| — | vazifalar/vazifalar.module.ts |
Kanon qarori: fayl turi Nest uslubida (*.controller.ts, *.service.ts, *.module.ts) — har Nest dasturchisi tanisin. Mavzu so'zi esa o'zbekcha (vazifalar, eksport) — loyiha 25-qismdan beri o'zbekcha. Omborlar, sxemalar, kursor.ts kabi fayllar o'zgarmaydi.
Tekshirib ko'ring: Hamkasbingiz
nest g resource vazifalarnivazifalar-apipapkasida yurgizmoqchi. Nimaga e'tibor berishi kerak?
Javob
Kamida uch narsaga. Birinchidan, vazifalar/ papkasi allaqachon bor — avval --dry-run bilan qaysi fayllar yozilishini ko'rsin. Ikkinchidan, generator .js importlar yozadi, loyiha esa .ts importlar ishlatadi. Uchinchidan, @nestjs/mapped-types ni "*" bilan qo'shadi. Kanon resurslarni qo'lda yozdi — mavjud kod ko'chirilgani uchun shablon kerak emas edi.
8. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
SyntaxError: Invalid or unexpected token (@ da) |
Nest kodini node fayl.ts bilan yurgizish |
nest build + node dist/main.js |
TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled. |
parametr xususiyati + erasableSyntaxOnly |
bayroqni olib tashlang |
ERR_MODULE_NOT_FOUND … dist/x.ts |
SWC .ts importlarni almashtirmaydi |
tsc builder yoki .js importlar |
dist/ da o'chirilgan faylning JS'i qolgan |
deleteOutDir yo'q |
nest-cli.json da deleteOutDir: true |
Testlar src/**/*.spec.ts ni topmaydi |
vitest.config.ts include boshqa |
include ni loyihaga moslang |
@nestjs/... yangilanib, loyiha buzildi |
^ yoki "*" versiyalar |
--save-exact |
9. Mashqlar
Mashqlar kurs/mashqlar/30/02-nest-cli/ da.
1-mashq (oson): qaysi fayl?
Har ishga mos faylni yozing:
"type": "module"qatori turadigan fayl —deleteOutDirsozlamasi turadigan fayl —emitDecoratorMetadatayoqiladigan fayl —NestFactory.createchaqiriladigan fayl —- Build natijasi tushadigan papka —
Yechim
- package.json — ESM loyiha belgisi.
- nest-cli.json — CLI sozlamasi: builder,
sourceRoot,deleteOutDir. - tsconfig.json —
experimentalDecoratorsbilan birga. - main.ts — kirish nuqtasi.
- dist —
tsconfig.jsondagioutDir.
2-mashq (o'rta): import kengaytmasini almashtirish
SWC muammosini tushunish uchun kichik model yozing. kengaytmaniAlmashtir(kod) funksiyasi JS matnidagi nisbiy importlarda .ts ni .js ga almashtirsin (tsc'ning rewriteRelativeImportExtensions ishi). Paket importlari ("@nestjs/core") va .js importlar o'zgarmasin. Ishora: regex (RegExp) — from "./…ts" yoki from "../…ts" ni toping; replace ga funksiya bering.
const kod = [
'import { NestFactory } from "@nestjs/core";',
'import { AppModule } from "./app.module.ts";',
'import { config } from "../config.ts";',
'import { x } from "./x.js";',
].join("\n");Yechim
const kod = [
'import { NestFactory } from "@nestjs/core";',
'import { AppModule } from "./app.module.ts";',
'import { config } from "../config.ts";',
'import { x } from "./x.js";',
].join("\n");
function kengaytmaniAlmashtir(matn) {
return matn.replace(
/from "(\.{1,2}\/[^"]+)\.ts"/g,
(_, yol) => `from "${yol}.js"`,
);
}
console.log(kengaytmaniAlmashtir(kod));Konsolda:
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module.js";
import { config } from "../config.js";
import { x } from "./x.js";\.{1,2}\/ — faqat ./ yoki ../ bilan boshlangan yo'l, ya'ni nisbiy import. @nestjs/core tegilmadi. SWC builder shu almashtirishni qilmagani uchun kanonda dist/ da config.ts ga import qolgan edi. Haqiqiy kompilyator matn bilan emas, sintaksis daraxti bilan ishlaydi — regex faqat g'oyani ko'rsatadi (masalan, izoh ichidagi from "./a.ts" ni ham almashtirib yuboradi).
3-mashq (qiyin): o'z demo loyihangiz
Alohida papkada nest new bilan loyiha yarating (darsdagi bayroqlar bilan), paketlarni o'rnating. So'ng:
nest g resource kitoblar --type rest --crudni avval--dry-runbilan, keyin haqiqiy yurgizing.@nestjs/mapped-typesversiyasini aniq qiling (npm ls @nestjs/mapped-typesko'rsatgan versiya).npm run buildvanpm testni yurgizing;dist/dagi fayllar sonini sanang.GET /kitoblar/5ga so'rov yuborib, javobni yozing.
Yechim
npx @nestjs/cli@12.0.9 new kutubxona --skip-git \
--skip-install -p npm --no-observe
cd kutubxona
npm install
npx nest g resource kitoblar --type rest --crud --dry-run
npx nest g resource kitoblar --type rest --crud
npm ls @nestjs/mapped-types
npm pkg set dependencies.@nestjs/mapped-types=12.0.0
npm run build
npm test
npm run start:devBoshqa terminalda: curl http://localhost:3000/kitoblar/5. Javob: This action returns a #5 kitoblar. --dry-run chiqishi xuddi shu CREATE va UPDATE src/app.module.ts qatorlarini ko'rsatadi, oxirida esa Dry run enabled. No files written to disk. qatori chiqadi — hech narsa yozilmaydi. Testlar: 3 fayl, 3 test. dist/ da yangi kitoblar/ papkasi paydo bo'ladi (dto/ va entities/ bilan).
Esda tuting: start:dev — nest start --watch; app.listen(3000) host bermagani uchun barcha tarmoq interfeyslarida ochiladi. Loyihada buni 127.0.0.1 bilan cheklaymiz (pastda).
10. Loyiha qadami: Nest skeleti vazifalar-api da
10.1 Reja
Qaysi holatdan boshlaymiz. Sizning vazifalar-api ingiz hozir 29-qism holatida: unda 28-qism auth'i va 29-qism integratsiyalari (fayl, email, bot, navbatlar) bor. Ko'chishni esa undan oldingi nuqtadan — 27-qism yakuniy commit'idan boshlaymiz. Sabab: avval yadro (CRUD, baza, kesh, testlar) Nest'ga o'tadi. Keyin uning ustiga auth va integratsiyalar qatlam-qatlam qaytadi. Hammasini birdan ko'chirsak, birinchi xatoda qaysi qatlam aybdorligini topish qiyin bo'ladi.
Buning uchun 27-qism commit'idan yangi nest tarmog'i (branch) ochamiz:
git log --oneline # 27-qism yakuniy commit'i xeshini toping
git switch -c nest <27-qism-commit>git switch -c yangi tarmoq yaratadi va darhol unga o'tadi. Endi loyihada ikki tarmoq bor:
| Tarmoq | Nima bor | Vazifasi |
|---|---|---|
main |
29-qism holati, Express | ishlab turgan API — tegmaymiz |
nest |
27-qism holati → Nest | 30-qismning hamma qadamlari shu yerda |
Auth va integratsiyalar yo'qolmaydi — ular main dagi commit'larda turibdi. Qism oxirida ularni nest tarmog'iga git checkout <commit> -- <fayl> bilan bittalab qaytaramiz: 28-qism auth fayllarini Passport NestJS'da darsida, 29-qism integratsiyalarini Fayl yuklash NestJS'da darsida.
Bu qadamda nima qilamiz. nest tarmog'idagi eski Express kodi to'liq ishlashda davom etadi (npm run start:express). Yonida Nest skeleti paydo bo'ladi: bitta modul, bitta GET /salom marshruti, bitta test. Keyingi to'rt darsda haqiqiy marshrutlar shu skeletga ko'chadi.
10.2 tsconfig.json
Uch o'zgarish (boshqa qatorlar 27-qismdagidek qoladi):
- "erasableSyntaxOnly": true,
"verbatimModuleSyntax": true,
"allowImportingTsExtensions": true,
+ "rewriteRelativeImportExtensions": true,
+ "experimentalDecorators": true,
+ "emitDecoratorMetadata": true,
"noEmit": true,include ro'yxatiga "vitest.config.ts" ham qo'shiladi.
erasableSyntaxOnlyketdi — «Build» bo'limidagi TS1294 sababli.rewriteRelativeImportExtensions—tscbuild'da./app.module.tsni./app.module.jsga almashtiradi. Shunda 25–27 dagi hamma import (.tskengaytmali) o'zgarmaydi. Nest hujjati esa.jsyozadi — ikkalasi ishlaydi; farqi SWC'da ko'rindi.noEmit: trueqoladi:npm run tipfaqat tekshiradi. Build uchun alohida fayl.
10.3 Build fayllari
tsconfig.build.json:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": false,
"rootDir": "./src",
"outDir": "./dist",
"sourceMap": true,
"incremental": true,
"tsBuildInfoFile": "./dist/.tsbuildinfo"
},
"include": ["src"],
"exclude": ["node_modules", "test", "dist", "**/*.spec.ts"]
}nest-cli.json:
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"entryFile": "main",
"compilerOptions": {
"deleteOutDir": true,
"tsConfigPath": "tsconfig.build.json"
}
}tsConfigPath — nest build qaysi tsconfig bilan ishlashi. entryFile: "main" — nest start qaysi faylni yurgizishi (dist/main.js).
10.4 Kod: modul, controller, kirish nuqtasi
src/salom.controller.ts:
// salom.controller.ts — skeletning birinchi marshruti
// (keyinroq o'chiriladi — o'rniga /v1/vazifalar keladi)
import { Controller, Get } from "@nestjs/common";
@Controller("salom")
export class SalomController {
@Get()
salom(): { xabar: string } {
return { xabar: "Salom, Nest!" };
}
}src/app.module.ts:
// app.module.ts — ildiz modul: ilova shu moduldan boshlab
// yig'iladi (imports daraxti)
import { Module } from "@nestjs/common";
import { SalomController } from "./salom.controller.ts";
@Module({
controllers: [SalomController],
})
export class AppModule {}src/main.ts:
// main.ts — Nest kirish nuqtasi (skelet). API hozircha Express'da
// (src/server.ts, `npm run start:express`); keyingi darslarda
// marshrutlar modul-modul Nest'ga ko'chadi (strangler)
import "reflect-metadata";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module.ts";
const app = await NestFactory.create(AppModule);
// SIGTERM/SIGINT da modullarning yopish hook'lari chaqirilsin
app.enableShutdownHooks();
// Sukut — faqat lokal (25-qism): reverse proxy orqasida
// Node porti tashqariga ochilmasin
await app.listen(
Number(process.env["PORT"] ?? 3000),
process.env["HOST"] ?? "127.0.0.1",
);
console.log(`vazifalar-api (Nest): ${await app.getUrl()}`);Shablondan uch farq: bootstrap() funksiyasiz to'g'ridan top-level await; host 127.0.0.1 — reverse proxy darsidagi qoida; enableShutdownHooks() — Lifecycle hook'lar darsida. Kanon fayllarida izohlar bitta uzun qator edi — telefon uchun bo'ldik, kod o'zgarmagan.
10.5 Test va skriptlar
src/salom.controller.spec.ts — ikki test: controller'ni DI konteyneridan olish va haqiqiy HTTP so'rov (Supertest):
// salom.controller.spec.ts — Nest test moduli + HTTP (supertest)
import { afterAll, beforeAll, expect, test } from "vitest";
import { Test } from "@nestjs/testing";
import type { INestApplication } from "@nestjs/common";
import request from "supertest";
import type { App } from "supertest/types.js";
import { AppModule } from "./app.module.ts";
import { SalomController } from "./salom.controller.ts";
let app: INestApplication<App>;
beforeAll(async () => {
const modul = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = modul.createNestApplication();
await app.init();
});
afterAll(() => app.close());
test("controller to'g'ridan (DI konteyneridan olingan)", () => {
expect(app.get(SalomController).salom())
.toEqual({ xabar: "Salom, Nest!" });
});
test("GET /salom — HTTP orqali", async () => {
const r = await request(app.getHttpServer())
.get("/salom").expect(200);
expect(r.body).toEqual({ xabar: "Salom, Nest!" });
});INestApplication<App> — generik turi bilan. Usiz getHttpServer() any qaytaradi va ESLint no-unsafe-argument xatosini beradi.
vitest.config.ts:
// vitest.config.ts — Vite 8 (oxc) dekorator metama'lumotini
// tsconfig'dan oladi
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// eski node:test fayllari (test/*.test.ts) — `npm run test:eski`
include: ["src/**/*.spec.ts"],
},
});Vitest hozircha faqat yangi *.spec.ts larni yurgizadi. 25–27 dagi 112 ta test node:test da qoladi — ular API ko'chgach Vitest'ga o'tadi.
package.json skriptlari:
{
"build": "nest build",
"start": "node --env-file-if-exists=.env dist/main.js",
"start:dev": "nest start --watch",
"start:express": "node --env-file-if-exists=.env src/server.ts",
"test": "vitest run",
"test:eski": "node --test \"test/**/*.test.ts\"",
"tip": "tsc --noEmit",
"lint": "eslint . --max-warnings=0",
"check": "npm run tip && npm run lint && npm test && npm run test:eski"
}sxema, postinstall, db:* skriptlari o'zgarmaydi. 27-qismdagi dev (pino-pretty bilan) va test:qamrov olib tashlandi — o'rniga start:dev va Vitest qamrovi keyinroq keladi.
ESLint'ga bitta qoida (eslint.config.js, rules ichiga):
// Nest: `@Module({...}) export class AppModule {}` — bo'sh klass
// dekorator bilan ma'noli (metama'lumot tashuvchi)
"@typescript-eslint/no-extraneous-class": [
"error", { allowWithDecorator: true },
],Usiz strictTypeChecked bo'sh AppModule {} klassini "keraksiz klass" deydi. ignores da dist/ allaqachon bor.
10.6 Tekshiruv va commit
npm run check
npm run build
npm start
curl http://127.0.0.1:3000/salomKanon tekshiruvi (Node 24.21.0, NestJS 12.2.0, vitest 5.0.5):
--- npm run tip
exit 0 (5331 ms)
--- npm run lint
exit 0 (12192 ms)
--- npm run test
Test Files 1 passed (1)
Tests 2 passed (2)
--- npm run build
exit 0 (5942 ms)
--- Nest skelet: {"xabar":"Salom, Nest!"}Express API ham tekshirildi: 9 ta so'rov uch saqlash rejimida (Postgres, Prisma, Prisma + kesh) — javoblar o'zgarmadi. Biz ham kanon nusxasida npm run tip va npm test ni yurgizdik — 0 xato, 2/2.
Halol eslatma: kanonda test:eski bir yugurishda 113 test, fail 1 berdi, keyingi ikki yugurishda 111/111 o'tdi. Bu 27-qismdan qolgan beqaror (flaky) test — migratsiya.test. Sababi va tuzatilishi API Nest'ga o'tadigan darsda (Bootstrap: main.ts). Agar sizda ham bir marta yiqilsa — qayta yurgizing va xabarini o'qing.
Commit:
git add -A
M="build: NestJS 12 skeleti (ESM, nest build, Vitest)"
M+=" — API hozircha Express'da"
git commit -m "$M".gitignore da dist/ borligini tekshiring — build natijasi git'ga tushmasin.
11. Real ishda
- Yangi loyiha: jamoalar odatda
nest newbilan boshlaydi, keyin shablonni o'zlariga moslaydi: AGENTS.md va deploy skriptini o'chiradi, versiyalarni qotiradi, lint qoidalarini qo'shadi. - Build CI'da: Nest loyihasida
npm run buildmajburiy qadam. Docker image hamdist/dan yig'iladi (Dockerfile yozish). - SWC: katta Nest monorepolarida build vaqti daqiqalarga yetadi — o'shanda SWC'ga o'tiladi. Shart:
.jsimportlar. - Intervyu: "Nest loyihasida nega build kerak?", "
emitDecoratorMetadatanima beradi?", "nest g resourcenimalarni yaratadi?".
Xulosa
nest new— 17 fayllik ESM loyiha: Vitest, oxlint, Prettier; AGENTS.md vanest deploy— ixtiyoriy.- Nest kodi build talab qiladi: dekoratorlar va
design:paramtypes— kompilyator ishi; type stripping@da yiqiladi. nest buildsukuttsc; SWC uch baravar tez, lekin.tsimportlarni almashtirmaydi; webpack va Rspack ham bor.nest g resource8 fayl yasab, modulni ulaydi;"*"versiya va inglizcha birlik shakl — qo'lda tuzating.vazifalar-apiga skelet qo'shildi:tsconfig(dekoratorlar,rewriteRelativeImportExtensions),nest-cli.json,main.ts,GET /salom, Vitest.
Keyingi dars: Modullar — @Module ning to'rt maydoni, exports bo'lmasa nima bo'lishini haqiqiy xato bilan ko'ramiz va vazifalar-api ni modullarga bo'lamiz.
Manbalar
- NestJS hujjati — CLI Overview va Usage: https://docs.nestjs.com/cli/overview , https://docs.nestjs.com/cli/usages
- NestJS hujjati — Migration guide (v12: ESM, Vitest, oxlint, Node talablari): https://docs.nestjs.com/migration-guide
- NestJS hujjati — SWC recipe: https://docs.nestjs.com/recipes/swc
- TypeScript 5.7 —
rewriteRelativeImportExtensions: https://www.typescriptlang.org/tsconfig/#rewriteRelativeImportExtensions - TypeScript 5.8 —
erasableSyntaxOnly: https://www.typescriptlang.org/tsconfig/#erasableSyntaxOnly - Kanon (IlmHamroh, 2026-10-27):
nest newo'lchovi, holat tekshiruvi, builder o'lchovi.nest new,nest g resource, build,node src/main.tsva TS1294 — biz ishga tushirdik (2026-11-01, CLI 12.0.9, NestJS 12.2.0, tsc 6.0.3, Node 24.21.0).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!