Retseptlar7 min read

SWC

SWC (Speedy Web Compiler) - bu kompilyatsiya ham, bundling ham uchun ishlatilishi mumkin bo'lgan kengaytiriladigan Rust asosidagi platforma. SWC'ni Nest CLI bilan ishlatish develop

SWC (Speedy Web Compiler) - bu kompilyatsiya ham, bundling ham uchun ishlatilishi mumkin bo'lgan kengaytiriladigan Rust asosidagi platforma. SWC'ni Nest CLI bilan ishlatish development jarayonini sezilarli darajada tezlashtirishning sodda va samarali usulidir.

Hint

SWC standart TypeScript kompilyatoridan taxminan x20 marta tezroq.

O'rnatish

Boshlash uchun avval bir nechta paketni o'rnating:

Terminal
1$ npm i --save-dev @swc/cli @swc/core

Boshlash

O'rnatish tugagach, swc builder'ni Nest CLI bilan quyidagicha ishlatishingiz mumkin:

Terminal
1$ nest start -b swc
2# OR nest start --builder swc
Hint

Agar repository'ingiz monorepo bo'lsa, ushbu bo'lim ni ko'ring.

-b flag'ini uzatish o'rniga, nest-cli.json faylida compilerOptions.builder xossasini "swc" qilib ham qo'yishingiz mumkin:

JSON
1{
2  "compilerOptions": {
3    "builder": "swc"
4  }
5}

Builder xatti-harakatini moslashtirish uchun type ("swc") va options atributlarini o'z ichiga olgan obyekt uzatishingiz mumkin:

JSON
1{
2  "compilerOptions": {
3    "builder": {
4      "type": "swc",
5      "options": {
6        "swcrcPath": "infrastructure/.swcrc",
7      }
8    }
9  }
10}

Masalan, SWC .jsx va .tsx fayllarni ham kompilyatsiya qilishi uchun quyidagicha yozing:

JSON
1{
2  "compilerOptions": {
3    "builder": {
4      "type": "swc",
5      "options": { "extensions": [".ts", ".tsx", ".js", ".jsx"] }
6    },
7  }
8}

Ilovani watch mode'da ishga tushirish uchun quyidagi buyruqdan foydalaning:

Terminal
1$ nest start -b swc -w
2# OR nest start --builder swc --watch

Type checking

SWC o'zi mustaqil ravishda type checking bajarmaydi (standart TypeScript kompilyatoridan farqli ravishda). Uni yoqish uchun --type-check flag'idan foydalaning:

Terminal
1$ nest start -b swc --type-check

Bu buyruq Nest CLI'ga SWC bilan birga tsc ni noEmit rejimida ishga tushirishni buyuradi va u asinxron ravishda type checking bajaradi. Yana, --type-check flag'ini uzatish o'rniga nest-cli.json faylida compilerOptions.typeCheck ni true ga o'rnatishingiz ham mumkin:

JSON
1{
2  "compilerOptions": {
3    "builder": "swc",
4    "typeCheck": true
5  }
6}

CLI plugin'lar (SWC)

--type-check flag'i NestJS CLI plugin'larini avtomatik ishga tushiradi va keyin runtime vaqtida ilova yuklay oladigan serialized metadata faylini yaratadi.

SWC konfiguratsiyasi

SWC builder NestJS ilovalari talablariga mos holda oldindan sozlangan. Biroq siz loyiha root katalogida .swcrc faylini yaratib, opsiyalarni xohlaganingizcha sozlashingiz mumkin.

JSON
1{
2  "$schema": "https://swc.rs/schema.json",
3  "sourceMaps": true,
4  "jsc": {
5    "parser": {
6      "syntax": "typescript",
7      "decorators": true,
8      "dynamicImport": true
9    },
10    "baseUrl": "./"
11  },
12  "minify": false
13}

Monorepo

Agar repository monorepo bo'lsa, swc builder'ni ishlatish o'rniga webpack ni swc-loader bilan sozlashingiz kerak bo'ladi.

Avval kerakli paketni o'rnating:

Terminal
1$ npm i --save-dev swc-loader

O'rnatish tugagach, ilovangiz root katalogida webpack.config.js faylini yarating va unga quyidagi kodni yozing:

JavaScript
1const swcDefaultConfig = require('@nestjs/cli/lib/compiler/defaults/swc-defaults').swcDefaultsFactory().swcOptions;
2
3module.exports = {
4  module: {
5    rules: [
6      {
7        test: /\.ts$/,
8        exclude: /node_modules/,
9        use: {
10          loader: 'swc-loader',
11          options: swcDefaultConfig,
12        },
13      },
14    ],
15  },
16};

Monorepo va CLI plugin'lar

Agar siz CLI plugin'lardan foydalansangiz, swc-loader ularni avtomatik yuklamaydi. Buning o'rniga, ularni qo'lda yuklaydigan alohida fayl yaratishingiz kerak. Buning uchun main.ts yonida generate-metadata.ts faylini yarating va unga quyidagi kodni yozing:

TypeScript
1import { PluginMetadataGenerator } from '@nestjs/cli/lib/compiler/plugins/plugin-metadata-generator';
2import { ReadonlyVisitor } from '@nestjs/swagger/dist/plugin';
3
4const generator = new PluginMetadataGenerator();
5generator.generate({
6  visitors: [new ReadonlyVisitor({ introspectComments: true, pathToSource: __dirname })],
7  outputDir: __dirname,
8  watch: true,
9  tsconfigPath: 'apps/<name>/tsconfig.app.json',
10});
Hint

Bu misolda @nestjs/swagger plugin'i ishlatilgan, ammo siz istalgan plugin'dan foydalanishingiz mumkin.

generate() metodi quyidagi opsiyalarni qabul qiladi:

watchLoyiha o'zgarishlarini kuzatish kerakmi yoki yo'qmi.
tsconfigPathtsconfig.json fayliga yo'l. Joriy ish katalogiga (process.cwd()) nisbatan olinadi.
outputDirMetadata fayli saqlanadigan katalog yo'li.
visitorsMetadata yaratishda ishlatiladigan visitor'lar massivi.
filenameMetadata fayli nomi. Standart qiymati metadata.ts.
printDiagnosticsDiagnostika ma'lumotlarini konsolga chiqarish kerakmi. Standart qiymati true.

Oxirida generate-metadata skriptini alohida terminal oynasida quyidagi buyruq bilan ishga tushirishingiz mumkin:

Terminal
1$ npx ts-node src/generate-metadata.ts
2# OR npx ts-node apps/{YOUR_APP}/src/generate-metadata.ts

Keng uchraydigan muammolar

Agar ilovangizda TypeORM/MikroORM yoki boshqa ORM ishlatsangiz, circular import muammolariga duch kelishingiz mumkin. SWC circular import larni yaxshi boshqarmaydi, shuning uchun quyidagi workaround'dan foydalaning:

TypeScript
1@Entity()
2export class User {
3  @OneToOne(() => Profile, (profile) => profile.user)
4  profile: Relation<Profile>; // <--- see "Relation<>" type here instead of just "Profile"
5}
Hint

Relation turi typeorm paketidan export qilinadi.

Bu yondashuv xossa turining transpiled koddagi property metadata ichida saqlanib qolishining oldini oladi va shu bilan circular dependency muammolarini kamaytiradi.

Agar ORM'ingiz shunga o'xshash workaround bermasa, wrapper type'ni o'zingiz aniqlashingiz mumkin:

TypeScript
1/**
2 * Wrapper type used to circumvent ESM modules circular dependency issue
3 * caused by reflection metadata saving the type of the property.
4 */
5export type WrapperType<T> = T; // WrapperType === Relation

Loyihangizdagi barcha circular dependency injection holatlarida ham yuqorida ta'riflangan custom wrapper type'dan foydalanishingiz kerak bo'ladi:

TypeScript
1@Injectable()
2export class UsersService {
3  constructor(
4    @Inject(forwardRef(() => ProfileService))
5    private readonly profileService: WrapperType<ProfileService>,
6  ) {};
7}

Jest + SWC

SWC'ni Jest bilan ishlatish uchun quyidagi paketlarni o'rnatishingiz kerak:

Terminal
1$ npm i --save-dev jest @swc/core @swc/jest

O'rnatish tugagach, konfiguratsiyangizga qarab package.json yoki jest.config.js faylini quyidagicha yangilang:

JSON
1{
2  "jest": {
3    "transform": {
4      "^.+\\.(t|j)s?$": ["@swc/jest"]
5    }
6  }
7}

Bundan tashqari, .swcrc fayliga quyidagi transform xossalarini qo'shishingiz kerak bo'ladi: legacyDecorator, decoratorMetadata:

JSON
1{
2  "$schema": "https://swc.rs/schema.json",
3  "sourceMaps": true,
4  "jsc": {
5    "parser": {
6      "syntax": "typescript",
7      "decorators": true,
8      "dynamicImport": true
9    },
10    "transform": {
11      "legacyDecorator": true,
12      "decoratorMetadata": true
13    },
14    "baseUrl": "./"
15  },
16  "minify": false
17}

Agar loyihada NestJS CLI plugin'lari ishlatilsa, PluginMetadataGenerator ni qo'lda ishga tushirishingiz kerak bo'ladi. Batafsil ma'lumot uchun ushbu bo'lim ga qarang.

Vitest

Vitest - bu Vite bilan ishlash uchun mo'ljallangan tez va yengil test runner. U NestJS loyihalariga integratsiya qilinishi mumkin bo'lgan zamonaviy, tez va ishlatish oson testing yechimini taqdim etadi.

O'rnatish

Boshlash uchun avval kerakli paketlarni o'rnating:

Terminal
1$ npm i --save-dev vitest unplugin-swc @swc/core @vitest/coverage-v8

Konfiguratsiya

Ilovangiz root katalogida vitest.config.ts faylini yarating va unga quyidagi kodni yozing:

TypeScript
1import swc from 'unplugin-swc';
2import { defineConfig } from 'vitest/config';
3
4export default defineConfig({
5  test: {
6    globals: true,
7    root: './',
8  },
9  plugins: [
10    // This is required to build the test files with SWC
11    swc.vite({
12      // Explicitly set the module type to avoid inheriting this value from a `.swcrc` config file
13      module: { type: 'es6' },
14    }),
15  ],
16  resolve: {
17    alias: {
18      // Ensure Vitest correctly resolves TypeScript path aliases
19      'src': resolve(__dirname, './src'),
20    },
21  },
22});

Bu konfiguratsiya fayli Vitest muhiti, root katalog va SWC plugin'ini sozlaydi. Bundan tashqari, e2e testlar uchun alohida konfiguratsiya fayli ham yaratishingiz kerak bo'ladi. Unda test yo'lini ko'rsatadigan qo'shimcha include maydoni bo'ladi:

TypeScript
1import swc from 'unplugin-swc';
2import { defineConfig } from 'vitest/config';
3
4export default defineConfig({
5  test: {
6    include: ['**/*.e2e-spec.ts'],
7    globals: true,
8    root: './',
9  },
10  plugins: [swc.vite()],
11});

Bundan tashqari, testlarda TypeScript path'larini qo'llab-quvvatlash uchun alias opsiyalarini ham sozlashingiz mumkin:

TypeScript
1import swc from 'unplugin-swc';
2import { defineConfig } from 'vitest/config';
3
4export default defineConfig({
5  test: {
6    include: ['**/*.e2e-spec.ts'],
7    globals: true,
8    alias: {
9      '@src': './src',
10      '@test': './test',
11    },
12    root: './',
13  },
14  resolve: {
15    alias: {
16      '@src': './src',
17      '@test': './test',
18    },
19  },
20  plugins: [swc.vite()],
21});

Path alias'lar

Jest'dan farqli ravishda, Vitest src/ kabi TypeScript path alias'larini avtomatik resolve qilmaydi. Bu test vaqtida dependency resolution xatolariga olib kelishi mumkin. Buni tuzatish uchun vitest.config.ts fayliga quyidagi resolve.alias konfiguratsiyasini qo'shing:

TypeScript
1import { resolve } from 'path';
2
3export default defineConfig({
4  resolve: {
5    alias: {
6      'src': resolve(__dirname, './src'),
7    },
8  },
9});

Bu Vitest'ning modul import'larini to'g'ri resolve qilishini ta'minlaydi va yo'q dependency'lar bilan bog'liq xatolarni kamaytiradi.

E2E testlardagi import'larni yangilash

import * as request from 'supertest' ko'rinishidagi barcha E2E test import'larini import request from 'supertest' ga o'zgartiring. Bu kerak, chunki Vitest Vite bilan bundle qilinganda supertest uchun default import kutadi. Namespace import ushbu setup'da muammo keltirib chiqarishi mumkin.

Oxirida package.json ichidagi test script'larini quyidagicha yangilang:

JSON
1{
2  "scripts": {
3    "test": "vitest run",
4    "test:watch": "vitest",
5    "test:cov": "vitest run --coverage",
6    "test:debug": "vitest --inspect-brk --inspect --logHeapUsage --threads=false",
7    "test:e2e": "vitest run --config ./vitest.config.e2e.ts"
8  }
9}

Bu script'lar Vitest'ni testlarni ishga tushirish, o'zgarishlarni kuzatish, code coverage hisobotlarini yaratish va debug qilish uchun sozlaydi. test:e2e skripti esa maxsus konfiguratsiya fayli bilan E2E testlarni ishga tushirish uchun mo'ljallangan.

Ushbu setup bilan NestJS loyihangizda Vitest'dan foydalanishning afzalliklarini, jumladan tezroq test bajarilishi va zamonaviyroq testing tajribasini olasiz.

Hint

Ishlaydigan namunani ushbu repository da ko'rishingiz mumkin.