Détecter les routes automatiquement (file-based-routing)
Dans cette leçon, je te présente deux plugins : @react-router/fs-routes, et remix-flat-routes. Ces deux plugins permettent entre autre de détecter automatiquement les routes présentes dans le dossier `app/routes`, et éviter de les déclarer de manière explicite.
Dans tes projets React Router 7, tu as peut-être déjà éprouvé la lourdeur de déclarer manuellement chaque route dans app/routes.ts. Et si on automatisait tout ça ? Grâce au plugin remix-flat-routes, tu peux tirer parti du file-based routing inspiré de Remix et Next.js : tes fichiers et dossiers dans app/routes/ deviennent la source unique de vérité pour tes routes.
Pourquoi utiliser le file-based routing ?
- Gain de temps : plus besoin de mettre à jour
routes.tsà chaque nouvelle page. - Moins d’erreurs : la correspondance fichier ↔ URL suit une convention simple.
- Meilleure organisation : tes dossiers structurent directement ton URL, et vice versa.
Tip
Le file-based routing est optionnel : tu peux conserver ta config manuelle si tu préfères.
Installation du plugin
1npm install remix-flat-routes \2@react-router/remix-routes-option-adapter
1npm install
Configuration de app/routes.ts
On remplace le tableau statique par l’adaptateur remixRoutesOptionAdapter et flatRoutes :
1import { type RouteConfig } from '@react-router/dev/routes'2import { remixRoutesOptionAdapter } from3'@react-router/remix-routes-option-adapter'4import { flatRoutes } from 'remix-flat-routes'56// ^? Détecte automatiquement toutes les routes sous `app/routes`7export default remixRoutesOptionAdapter((defineRoutes) => {8return flatRoutes('routes', defineRoutes, {9ignoredRouteFiles: [10'.*', // tous les fichiers cachés11'**/*.css', // styles globales12'**/*.test.{js,jsx,ts,tsx}', // fichiers de test13'**/__*.*', // préfixe __14'**/*.server.*', // utilitaires serveur15'**/*.client.*', // utilitaires client16],17})18}) satisfies RouteConfig
Le paramètre
'routes'indique àflatRoutesle dossier à scanner.
Conventions de nommage
1app/2└── routes/3├── users+/4│ ├── _usersLayout.tsx # layout pour /users/*5│ ├── index.tsx # /users6│ ├── $userSlug.tsx # /users/:userSlug7│ └── export+/8│ ├── json.tsx # /users/export/json9│ ├── csv.tsx # /users/export/csv10│ └── pdf.tsx # /users/export/pdf11└── home.tsx # /home
- Le suffixe
+dansusers+active le dossier comme segment/users. _usersLayout.tsx(underscore en préfixe) crée un layout imbriqué.index.tsx→ route index du segment (équiv.index()en config).$userSlug.tsx→ segment dynamique:userSlug.export+→/exportà l’intérieur de/users.- Les fichiers
*.server.*ou*.client.*sont ignorés.
Pourquoi le `+` ?
Le + dans le nom du dossier indique à flatRoutes qu’il s’agit d’un
dossier de routes (et pas d’un utilitaire colocalisé).
Visualiser l’arborescence
Le CLI de React Router permet de “révéler” la config courante :
1npm run routes
1└── root2├── home.tsx3└── users+4├── index.tsx5├── $userSlug.tsx6├── _usersLayout.tsx7└── export+8├── json.tsx9├── csv.tsx10└── pdf.tsx
Avantages et bon usage
- Organisation : chaque dossier : fragment d’URL
- Clarté : un coup d’œil dans
app/routessuffit à comprendre ton routing - Moins de boilerplate : plus de routes hard-codées dans
routes.ts
Tip
Tu peux toujours combiner file-based routing et routes manuelles ;
ignoredRouteFiles t’offre toute la flexibilité.
Attention aux noms spéciaux
Si un fichier doit contenir “server” ou “client”, échappe-le avec des crochets :
my-route.[server].ts ou my-route.[client].tsx.
Exercices rapides
- Crée un dossier
blog+avec un_blogLayout.tsx,index.tsxet$slug.tsx. Vérifie l’arborescence avecnpm run routes. - Ajoute une convention pour ignorer tous les fichiers
.spec.tsxen les incluant dansignoredRouteFiles. - Renomme un ancien dossier de routes manuelles en format file-based et teste la navigation sur toutes les routes imbriquées.
Bonne exploration du file-based routing !
Comprendre les concepts fondamentaux
Quelle est la principale différence entre les composants client et serveur dans React ?
Optimisation des performances
Quelle technique est recommandée pour éviter les rendus inutiles dans React ?
Architecture des données
Quel hook permet de gérer les effets de bord dans un composant React ?