Configuration de Turborepo
Nous configurons Turborepo, en ajoutant les packages Typescript et Eslint.
Ajout des commandes typecheck et lint
Nous avons déjà ajouté le mot clé workspaces
dans le package.json
principal. Il informe NodeJS que nous utilisons un monorepo.
1{2"workspaces": ["frontend", "backend", "packages/*"]3}
Maintenant, lorsque nous installons nos dépendances avec npm install
, NodeJS saura qu'il doit installer les dépendances de chaque projet.
Nous avions déjà ajouté la commande dev
aux scripts
du package.json
. Elle exécute la commande turbo dev
1{2"name": "nestjs-remix-monorepo",3"version": "1.0.0",4"description": "",5"main": "index.js",6"scripts": {7"test": "echo \"Error: no test specified\" && exit 1",8"dev": "turbo dev"9},10"keywords": [],11"author": "",12"license": "ISC",13"packageManager": "npm@10.2.3",14"workspaces": ["frontend", "backend", "packages/*"]15}
Pourquoi turbo dev
? Parce que nous avons défini une pipeline nommée dev
dans la configuration Turborepo (le fichier turbo.json
)
Pour rappel, voici son contenu
1{2"$schema": "https://turbo.build/schema.json",3"pipeline": {4"build": {5"outputs": ["dist/**"]6},7"dev": {8"cache": false,9"persistent": true10}11}12}
Nous allons rajouter deux autres pipelines à cette configuration, pour utiliser Eslint et Typescript.
1{2"$schema": "https://turbo.build/schema.json",3"pipeline": {4"build": {5"outputs": ["dist/**"]6},7"dev": {8"cache": false,9"persistent": true10},11"typecheck": {},12"lint": {}13}14}
Il nous suffit de rajouter ces deux clés typecheck
et lint
, qui prendront le même nom que les scripts
que l'on va ajouter à nos fichiers package.json
.
Pour exécuter ces pipelines, nous devons aussi les rajouter au fichier package.json
principal :
1{2"name": "nestjs-remix-monorepo",3"version": "1.0.0",4"description": "",5"main": "index.js",6"scripts": {7"test": "echo \"Error: no test specified\" && exit 1",8"build": "turbo build",9"dev": "turbo dev",10"typecheck": "turbo typecheck",11"lint": "turbo lint"12},13"keywords": [],14"author": "",15"license": "ISC",16"packageManager": "npm@10.2.3",17"workspaces": ["frontend", "backend", "packages/*"]18}
Maintenant, lorsque nous exécutons la commande npm run typecheck
, Turborepo va regarder la configuration de chaque projet (frontend/package.json
, backend/package.json
, packages/eslint-config/package.json
, packages/typescript-config/package.json
respectivements).
Si ces projets possèdent un script nommé typecheck
, Turbo va l'exécuter en parallèle. S'ils n'en possèdent pas, Turbo ne l'exécutera pas.
En lançant la commande npm run dev
à la racine du monorepo, on exécute le scripts
nommé dev
de chaque projet. Mais seul le projet backend
possède un script nommé dev
. C'est ce que nous souhaitons : Le serveur NestJS va se charger de lancer l'application Remix.js. Nous n'avons pas besoin d'avoir une commande dev
dans le package.json
du frontend. Si c'est le cas, nous devons la retirer.
Pour rappel, voici notre package.json
.
1{2"name": "@virgile/frontend",3"private": true,4"sideEffects": false,5"type": "module",6"main": "./index.cjs",7"types": "./index.d.cts",8"scripts": {9"start": "remix-serve ./build/server/index.js",10"old-dev": "remix vite:dev",11"build": "remix vite:build",12"lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",13"typecheck": "tsc"14},15"dependencies": {16"@remix-run/node": "^2.8.1",17"@remix-run/react": "^2.8.1",18"@remix-run/serve": "^2.8.1",19"isbot": "^5.1.2",20"react": "^18.2.0",21"react-dom": "^18.2.0",22"remix-flat-routes": "^0.6.4"23},24"devDependencies": {25"@remix-run/dev": "^2.8.1",26"@types/react": "^18.2.67",27"@types/react-dom": "^18.2.22",28"@virgile/eslint-config": "*",29"@virgile/typescript-config": "*",30"eslint": "^8.57.0",31"eslint-import-resolver-typescript": "^3.6.1",32"eslint-plugin-import": "^2.29.1",33"eslint-plugin-jsx-a11y": "^6.8.0",34"eslint-plugin-react": "^7.34.1",35"eslint-plugin-react-hooks": "^4.6.0",36"eslint-plugin-remix-react-routes": "^1.0.5",37"eslint-plugin-tailwindcss": "^3.15.1",38"typescript": "^5.4.3",39"vite": "^5.2.2",40"vite-tsconfig-paths": "^4.3.2"41},42"engines": {43"node": ">=18.0.0"44}45}
Il possède les commandes suivantes :
- Une commande
typecheck
, pour détecter les erreurs Typescript - Une commande
lint
pour détecter les erreurs Eslint (et appliquer les bonnes pratiques) - Une commande
build
pour construire l'application Remix.js
En environnement de développement, NestJS se charge de build le code source de Remix. Cependant en production, nous avons besoin de la commande build
de Remix pour compiler le code source du frontend.
Ajout de la commande build
Notre fichier de configuration turbo.json
contient déjà une commande build
. Mais elle est erronée (nous avons laissé la configuration par défaut).
1{2"$schema": "https://turbo.build/schema.json",3"pipeline": {4"build": {5"outputs": ["dist/**"] // <= Cette ligne est erronée6},7"dev": {8"cache": false,9"persistent": true10},11"typecheck": {},12"lint": {}13}14}
Effectivement, l'instruction outputs
défini un tableau de dossiers contenant le code source compilé, une fois la commande build
exécutée. Mais le chemin n'est pas bon.
Notre application NestJS compile bien son code dans le dossier dist
, le bon chemin est donc backend/dist/**
.
Notre application Remix compile son code dans le dossier build
, le bon chemin est donc frontend/build/**
.
De plus, avant de pouvoir compiler le code source de NestJS, nous avons besoin de compiler l'application Remix. (Car NestJS utilise le build de Remix, dans son main.ts
. Il est donc important de build le code source de Remix, avant de build l'application NestJS.)
Comme notre backend dépend du frontend (nous avions ajouté l'instruction ci-dessous), Turborepo saura qu'il faut d'abord compiler le frontend avant de compiler le backend.
1{2"dependencies": {3"@virgile/frontend": "*"4}5}
Ajoutons la clé "dependsOn": ["^build"]
au fichier de configuration pour que Turbo en soit informé.
1{2"$schema": "https://turbo.build/schema.json",3"pipeline": {4"build": {5"outputs": ["backend/dist/**", "frontend/build/**"],6"dependsOn": ["^build"]7},8"dev": {9"cache": false,10"persistent": true11},12"typecheck": {},13"lint": {}14}15}
Maintenant, exécuter la commande npm run build
à la racine du monorepo va compiler le code source de l'application Remix, puis celui de l'application NestJS.
Cependant, nous avons un problème dans le terminal. Comme nous utilisons un monorepo, nous avons besoin d'utiliser un chemin absolu dans le fichier de configuration vite.config.ts