SWC
SWC (Speedy Web Compiler) est une plateforme extensible basée sur Rust qui peut être utilisée pour la compilation et le bundling. Utiliser SWC avec Nest CLI est un excellent moyen simple d’accélérer considérablement votre processus de développement.
Installation
Pour commencer, installez d’abord quelques paquets :
$ npm i --save-dev @swc/cli @swc/core
Getting started
Une fois le processus d’installation terminé, vous pouvez utiliser le builder swc
avec Nest CLI, comme suit :
$ nest start -b swc# OU nest start --builder swc
Au lieu de passer le flag -b
, vous pouvez également définir simplement la propriété compilerOptions.builder
à "swc"
dans votre fichier nest-cli.json
, comme ceci :
{ "compilerOptions": { "builder": "swc" }}
Pour personnaliser le comportement du builder, vous pouvez passer un objet contenant deux attributs, type
("swc"
) et options
, comme suit :
{ "compilerOptions": { "builder": { "type": "swc", "options": { "swcrcPath": "infrastructure/.swcrc" } } }}
Pour exécuter l’application en mode watch, utilisez la commande suivante :
$ nest start -b swc -w# OU nest start --builder swc --watch
Type checking
SWC ne réalise pas de vérification de type lui-même (contrairement au compilateur TypeScript par défaut), donc pour l’activer, vous devez utiliser le flag --type-check
:
$ nest start -b swc --type-check
Cette commande demandera à Nest CLI d’exécuter tsc
en mode noEmit
avec SWC, qui effectuera la vérification de type de manière asynchrone. Au lieu de passer le flag --type-check
, vous pouvez également définir simplement la propriété compilerOptions.typeCheck
à true
dans votre fichier nest-cli.json
, comme ceci :
{ "compilerOptions": { "builder": "swc", "typeCheck": true }}
CLI Plugins (SWC)
Le flag --type-check
exécutera automatiquement les plugins NestJS CLI et produira un fichier de métadonnées sérialisé qui pourra être chargé par l’application au runtime.
SWC configuration
Le builder SWC est pré-configuré pour correspondre aux exigences des applications NestJS. Cependant, vous pouvez personnaliser la configuration en créant un fichier .swcrc
dans le répertoire racine et en ajustant les options à votre guise.
{ "$schema": "https://json.schemastore.org/swcrc", "sourceMaps": true, "jsc": { "parser": { "syntax": "typescript", "decorators": true, "dynamicImport": true }, "baseUrl": "./" }, "minify": false}
Monorepo
Si votre dépôt est un monorepo, alors au lieu d’utiliser le builder swc
, vous devez configurer webpack
pour utiliser swc-loader
.
D’abord, installons le paquet requis :
$ npm i --save-dev swc-loader
Une fois l’installation terminée, créez un fichier webpack.config.js
dans le répertoire racine de votre application avec le contenu suivant :
const swcDefaultConfig = require('@nestjs/cli/lib/compiler/defaults/swc-defaults').swcDefaultsFactory();
module.exports = { module: { rules: [ { test: /\.ts$/, exclude: /node_modules/, use: { loader: 'swc-loader', options: swcDefaultConfig, }, }, ], },};
Monorepo and CLI plugins
Si vous utilisez des plugins CLI, swc-loader
ne les chargera pas automatiquement. Au lieu de cela, vous devez créer un fichier séparé qui les chargera manuellement. Pour ce faire, déclarez un fichier generate-metadata.ts
près du fichier main.ts
avec le contenu suivant :
import { PluginMetadataGenerator } from '@nestjs/cli/lib/compiler/plugins';import { ReadonlyVisitor } from '@nestjs/swagger/dist/plugin';
const generator = new PluginMetadataGenerator();generator.generate({ visitors: [new ReadonlyVisitor({ introspectComments: true, pathToSource: __dirname })], outputDir: __dirname, watch: true, tsconfigPath: 'apps/<name>/tsconfig.app.json',});
Le méthode generate()
accepte les options suivantes :
Option | Description |
---|---|
watch | Si vous souhaitez surveiller le projet pour les changements. |
tsconfigPath | Chemin vers le fichier tsconfig.json . Relatif au répertoire de travail actuel (process.cwd() ). |
outputDir | Chemin vers le répertoire où le fichier de métadonnées sera sauvegardé. |
visitors | Un tableau de visiteurs qui seront utilisés pour générer des métadonnées. |
filename | Le nom du fichier de métadonnées. Par défaut metadata.ts . |
printDiagnostics | Si vous souhaitez imprimer les diagnostics dans la console. Par défaut true . |
Enfin, vous pouvez exécuter le script generate-metadata
dans une fenêtre de terminal séparée avec la commande suivante :
$ npx ts-node src/generate-metadata.ts# OU npx ts-node apps/{YOUR_APP}/src/generate-metadata.ts
Common pitfalls
Si vous utilisez TypeORM/MikroORM ou tout autre ORM dans votre application, vous pouvez rencontrer des problèmes d’importation circulaire. SWC ne gère pas bien les imports circulaires, donc vous devriez utiliser la solution de contournement suivante :
@Entity()export class User { @OneToOne(() => Profile, (profile) => profile.user) profile: Relation<Profile>; // <--- voir le type "Relation<>" ici au lieu de simplement "Profile"}
Cela empêche le type de la propriété d’être enregistré dans le code transpilé dans les métadonnées de la propriété, empêchant ainsi les problèmes de dépendance circulaire.
Si votre ORM ne fournit pas une solution de contournement similaire, vous pouvez définir vous-même le type wrapper :
/** * Type wrapper utilisé pour contourner le problème de dépendance circulaire des modules ESM * causé par la sauvegarde des métadonnées de réflexion du type de la propriété. */export type WrapperType<T> = T; // WrapperType === Relation
Pour toutes les injections de dépendance circulaires dans votre projet, vous devrez également utiliser le type wrapper personnalisé décrit ci-dessus :
@Injectable()export class UserService { constructor( @Inject(forwardRef(() => ProfileService)) private readonly profileService: WrapperType<ProfileService>, ) {}}
Jest + SWC
Pour utiliser SWC avec Jest, vous devez installer les paquets suivants :
$ npm i --save-dev jest @swc/core @swc/jest
Une fois l’installation terminée, mettez à jour le fichier package.json
/.jest.config.js
(selon votre configuration) avec le contenu suivant :
{ "jest": { "transform": { "^.+\\.(t|j)s?$": ["@swc/jest"] } }}
De plus, vous devrez ajouter les propriétés transform
suivantes à votre fichier .swcrc
: legacyDecorator
, decoratorMetadata
:
{ "$schema": "https://json.schemastore.org/swcrc", "sourceMaps": true, "jsc": { "parser": { "syntax": "typescript", "decorators": true, "dynamicImport": true }, "transform": { "legacyDecorator": true, "decoratorMetadata": true }, "baseUrl": "./" }, "minify": false}
Si vous utilisez les plugins NestJS CLI dans votre projet, vous devrez exécuter PluginMetadataGenerator
manuellement. Consultez cette section pour en savoir plus.
Vitest
Vitest est un exécuteur de tests rapide et léger, conçu pour travailler avec Vite. Il fournit une solution de test moderne, rapide et facile à utiliser qui peut être intégrée aux projets NestJS.
Installation
Pour commencer, installez d’abord les paquets requis :
$ npm i --save-dev vitest unplugin-swc @swc/core @vitest/coverage-v8
Configuration
Créez un fichier vitest.config.ts
dans le répertoire racine de votre application avec le contenu suivant :
import swc from 'unplugin-swc';import { defineConfig } from 'vitest/config';
export default defineConfig({ test: { globals: true, root: './', }, plugins: [ // Ceci est requis pour construire les fichiers de test avec SWC swc.vite({ // Définir explicitement le type de module pour éviter d'hériter de cette valeur d'un fichier de configuration `.swcrc` module: { type: 'es6' }, }), ],});
Ce fichier de configuration configure l’environnement Vitest, le répertoire racine et le plugin SWC. Vous devez également créer un fichier de configuration séparé pour les tests E2E, avec un champ include
supplémentaire qui spécifie l’expression régulière du chemin de test :
import swc from 'unplugin-swc';import { defineConfig } from 'vitest/config';
export default defineConfig({ test: { include: ['**/*.e2e-spec.ts'], globals: true, root: './', }, plugins: [swc.vite()],});
De plus, vous pouvez définir les options alias
pour prendre en charge les chemins TypeScript dans vos tests :
import swc from 'unplugin-swc';import { defineConfig } from 'vitest/config';
export default defineConfig({ test: { include: ['**/*.e2e-spec.ts'], globals: true, alias: { '@src': './src', '@test': './test', }, root: './', }, resolve: { alias: { '@src': './src', '@test': './test', }, }, plugins: [swc.vite()],});
Mettre à jour les imports dans les tests E2E
Changez les imports de tout test E2E utilisant import * as request from 'supertest'
vers import request from 'supertest'
. Cela est nécessaire car Vitest, lorsqu’il est bundlé avec Vite, s’attend à un import par défaut pour supertest. Utiliser un import namespace peut provoquer des problèmes dans cette configuration spécifique.
Enfin, mettez à jour les scripts de test dans votre fichier package.json vers :
{ "scripts": { "test": "vitest run", "test:watch": "vitest", "test:cov": "vitest run --coverage", "test:debug": "vitest --inspect-brk --inspect --logHeapUsage --threads=false", "test:e2e": "vitest run --config ./vitest.config.e2e.ts" }}
Ces scripts configurent Vitest pour exécuter des tests, surveiller les changements, générer des rapports de couverture de code et déboguer. Le script test:e2e
est spécifiquement destiné à exécuter des tests E2E avec un fichier de configuration personnalisé.
Avec cette configuration, vous pouvez désormais profiter des avantages d’utilisation de Vitest dans votre projet NestJS, notamment une exécution de test plus rapide et une expérience de test plus moderne.