Nous configurons un nouveau projet Remix qui va contenir toute la logique frontend de notre application.
Nous devons d'abord reculer d'un dossier pour créer le projet Remix, à la racine de stack-remix-nestjs
.
1cd .. # Pour remonter d'un dossier2npx create-remix@latest # Pour créer un nouveau projet Remix
Nous appelons le projet frontend
. Et nous répondons Non
à la question Voulez-vous instancier un nouveau repository git ?
.
On devrait maintenant avoir un dossier frontend
à la racine de stack-remix-nestjs
.
Attention. Nous allons créer un fichier
index.cjs
qui sera exécuté et interprété par l'application NestJS. Il utilise la syntaxe CommonJS, qui est compatible avec NestJS.
1const path = require('node:path');23let devServer;4const SERVER_DIR = path.join(__dirname, 'build/server/index.js');5const PUBLIC_DIR = path.join(__dirname, 'build/client');67module.exports.getPublicDir = function getPublicDir() {8return PUBLIC_DIR;9};1011module.exports.getServerBuild = async function getServerBuild() {12if (process.env.NODE_ENV === 'production' || devServer === null) {13return import(SERVER_DIR);14}15const ssrModule = await devServer.ssrLoadModule('virtual:remix/server-build');16return ssrModule;17};1819module.exports.startDevServer = async function startDevServer(app) {20if (process.env.NODE_ENV === 'production') return;21const vite = await import('vite');22devServer = await vite.createServer({23server: { middlewareMode: 'true' },24root: __dirname,25});2627app.use(devServer.middlewares);28return devServer;29// ...continues30};
Ce fichier déclare trois fonctions que nous utiliserons dans l'application NestJS :
getPublicDir
: retourne le chemin du dossier build/client
getServerBuild
: retourne le module server/index.js
de l'application RemixstartDevServer
: démarre le serveur de développement de RemixPour bénéficier de l'autocomplétion, nous devons créer un fichier index.d.cts
qui va déclarer les types de ces fonctions.
1declare module '@virgile/frontend' {2// <= Nom du module, à adapter selon le nom de votre projet3export function getPublicDir(): string;4export function getServerBuild(): Promise<any>;5export function startDevServer(app: any): Promise<void>;6}
Après avoir créé ces deux fichiers, nous devons modifier le fichier package.json
de Remix pour que NestJS connaisse son point d'entrée (et sa déclaration de types).
C'est seulement après avoir ajouté cette instruction qu'on bénéficiera de l'auto-complétion du module
frontend
.
Voilà un package.json
complet.
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"@conform-to/react": "^1.1.0",17"@conform-to/zod": "^1.1.0",18"@radix-ui/react-slot": "^1.0.2",19"@remix-run/node": "^2.8.1",20"@remix-run/react": "^2.8.1",21"@remix-run/serve": "^2.8.1",22"class-variance-authority": "^0.7.0",23"clsx": "^2.1.0",24"isbot": "^5.1.2",25"lucide-react": "^0.365.0",26"react": "^18.2.0",27"react-dom": "^18.2.0",28"remix-flat-routes": "^0.6.4",29"tailwind-merge": "^2.2.2",30"tailwindcss-animate": "^1.0.7",31"zod": "^3.22.4"32},33"devDependencies": {34"@remix-run/dev": "^2.8.1",35"@types/react": "^18.2.67",36"@types/react-dom": "^18.2.22",37"@virgile/eslint-config": "*",38"@virgile/typescript-config": "*",39"autoprefixer": "^10.4.19",40"eslint": "^8.57.0",41"eslint-import-resolver-typescript": "^3.6.1",42"eslint-plugin-import": "^2.29.1",43"eslint-plugin-jsx-a11y": "^6.8.0",44"eslint-plugin-react": "^7.34.1",45"eslint-plugin-react-hooks": "^4.6.0",46"eslint-plugin-remix-react-routes": "^1.0.5",47"eslint-plugin-tailwindcss": "^3.15.1",48"postcss": "^8.4.38",49"tailwindcss": "^3.4.3",50"typescript": "^5.4.3",51"vite": "^5.2.2",52"vite-tsconfig-paths": "^4.3.2"53},54"engines": {55"node": ">=18.0.0"56}57}
Ce qui nous intéresse ici, ce sont les deux premières lignes :
1"main": "./index.cjs",2"types": "./index.d.cts",
Grâce à l'ajout de ces deux lignes, toute application qui importera le module @virgile/frontend
bénéficiera de l'autocomplétion des fonctions getPublicDir
, getServerBuild
et startDevServer
.
Nous avons terminé la configuration de ces deux projets pour l'instant. Nous allons maintenant configurer le monorepo pour qu'ils puissent communiquer entre eux.