Comment créer une route ressource

La route ressource te permet de créer un endpoint API te permettant de renvoyer une réponse au format JSON, PDF, XML, CSV ... À peu près tous les formats imaginables qu'un serveur peut renvoyer. Pour la mettre en place, il suffit de ne pas exporter de composant React par défaut.

4 min read

Continuez votre apprentissage

Accédez aux 9 modules et 76 leçons de cette formation.

599

Accès à vie · Garantie 30 jours

Dans React Router 7, une route ressource (resource route) n’affiche pas de composant React, mais renvoie directement une réponse HTTP (JSON, CSV, PDF, XML, etc.). C’est idéal pour proposer une API interne ou générer un fichier à télécharger (sitemap, robots.txt, export de données, etc.).

Tu vas apprendre à :

  1. Créer une route JSON avec Response.json.
  2. Générer un CSV et un PDF via new Response.
  3. Déclarer ces routes dans app/routes.ts.
  4. Ajouter des liens <Link reloadDocument> pour forcer le téléchargement.

1. Route JSON avec Response.json

1.1. Créer le fichier de route

app/routes/users.json.tsx
1
import { getUsers } from '~/users.server';
2
import type { LoaderFunctionArgs } from 'react-router';
3
4
// @callout: La fonction loader renvoie du JSON directement
5
export async function loader({}: LoaderFunctionArgs) {
6
// ^? Méthode utilitaire pour JSON et headers par défaut
7
return Response.json(
8
{ users: await getUsers() },
9
{
10
headers: {
11
'Cache-Control': 'public, max-age=3600', // ^? Mise en cache 1 heure
12
},
13
}
14
);
15
}

1.2. Déclarer la route

app/routes.ts
1
import { type RouteConfig, index, route } from '@react-router/dev/routes';
2
3
export default [
4
index('routes/home.tsx'),
5
// ^? Route JSON à la racine
6
route('users.json', 'routes/users.json.tsx'),
7
] satisfies RouteConfig;

2. Export CSV manuellement

2.1. Fichier CSV

app/routes/users.csv.tsx
1
import { getUsers } from '~/users.server';
2
3
// @callout: Génère une chaîne CSV à partir d’un tableau
4
export async function loader() {
5
const users = await getUsers();
6
// 1. Entête
7
let csv = ['id', 'name', 'slug'].join(',') + '\r\n';
8
// 2. Lignes de données
9
users.forEach((u) => {
10
csv += [u.id, u.name, u.slug].join(',') + '\r\n';
11
});
12
13
return new Response(csv, {
14
headers: {
15
'Content-Type': 'text/csv',
16
'Content-Disposition': `attachment; filename="users.csv"`,
17
},
18
});
19
}

2.2. Déclaration dans routes.ts

app/routes.ts
1
import { type RouteConfig, index, route } from '@react-router/dev/routes';
2
3
export default [
4
index('routes/home.tsx'),
5
route('users.json', 'routes/users.json.tsx'),
6
route('users.csv', 'routes/users.csv.tsx'),
7
] satisfies RouteConfig;

3. Générez un PDF avec PDFKit

3.1. Installer PDFKit

Terminal
1
npm install pdfkit @types/pdfkit

3.2. Route PDF

app/routes/users.pdf.tsx
1
import PDFDocument from 'pdfkit';
2
import { getUsers } from '~/users.server';
3
4
// @callout: PDFKit génère un flux de données PDF
5
export async function loader() {
6
const users = await getUsers();
7
const doc = new PDFDocument();
8
const chunks: Uint8Array[] = [];
9
10
doc.on('data', (chunk) => chunks.push(chunk));
11
doc.fontSize(16).text('Users list', { align: 'center' }).moveDown();
12
13
users.forEach((u) => {
14
doc.fontSize(12).text(`${u.id}: ${u.name}`).moveDown(0.5);
15
});
16
17
doc.end();
18
19
// ^? Attendre la fin du flux avant de répondre
20
return new Promise<Response>((resolve) => {
21
doc.on('end', () => {
22
const pdfBuffer = Buffer.concat(chunks);
23
resolve(
24
new Response(pdfBuffer, {
25
headers: {
26
'Content-Type': 'application/pdf',
27
'Content-Disposition': `attachment; filename="users.pdf"`,
28
},
29
})
30
);
31
});
32
});
33
}

3.3. Ajouter dans routes.ts

app/routes.ts
1
import { type RouteConfig, index, route } from '@react-router/dev/routes';
2
3
export default [
4
index('routes/home.tsx'),
5
route('users.json', 'routes/users.json.tsx'),
6
route('users.csv', 'routes/users.csv.tsx'),
7
route('users.pdf', 'routes/users.pdf.tsx'),
8
] satisfies RouteConfig;

4. Lier dans le layout

Pour permettre à l’utilisateur de télécharger ces fichiers, ajoute des liens avec reloadDocument :

app/routes/_usersLayout.tsx
1
import { Link, href, Outlet, useLoaderData } from 'react-router';
2
import { getUsers } from '~/users.server';
3
4
export default function UsersLayout() {
5
const users = useLoaderData<typeof loader>().users;
6
return (
7
<div>
8
<nav className="flex gap-2">
9
<Link to={href('/users.json')} reloadDocument className="btn">
10
JSON
11
</Link>
12
<Link to={href('/users.csv')} reloadDocument className="btn">
13
CSV
14
</Link>
15
<Link to={href('/users.pdf')} reloadDocument className="btn">
16
PDF
17
</Link>
18
</nav>
19
<Outlet />
20
</div>
21
);
22
}

Points clés

  • Une route ressource n’exporte pas de composant par défaut.
  • Utilise Response.json(...) ou new Response(...) pour contrôler le body et les headers.
  • Déclare ces routes au même niveau que tes pages (app/routes.ts).
  • <Link reloadDocument> force le téléchargement de l’API/fichier.
  • Très utile pour exposer un sitemap.xml, robots.txt, ou des API simples.

Exercices rapides

  1. Crée une route /sitemap.xml qui renvoie un plan de site au format XML (éléments <url>).
  2. Gère une route robots.txt statique via new Response(...) et ajoute-la dans le layout root.
  3. Simule une route ressource /api/avatar.png qui renvoie une image binaire stockée dans public/.
Inclus
Quiz interactifTestez vos connaissances
Validez votre compréhension du module avec notre quiz interactif personnalisé.
1

Comprendre les concepts fondamentaux

Quelle est la principale différence entre les composants client et serveur dans React ?

Les composants client s'exécutent uniquement dans le navigateur
Les composants serveur peuvent utiliser useState
2

Optimisation des performances

Quelle technique est recommandée pour éviter les rendus inutiles dans React ?

Utiliser React.memo pour les composants fonctionnels
Ajouter plus d'états locaux
3

Architecture des données

Quel hook permet de gérer les effets de bord dans un composant React ?

useEffect
useState

Débloquez ce quiz et tous les autres contenus