Le piège numéro un des Single Page Applications (React, Vue, Angular) : apprenez pourquoi rafraîchir une URL profonde provoque une erreur 404 du serveur et comment configurer la règle universelle de réécriture (SPA Fallback) sur tous les hébergeurs.
La navigation par liens fonctionne en local grâce à l'API history.pushState sans faire de requête HTTP au serveur.
Au rafraîchissement, le serveur cherche un dossier physique correspondant à l'URL. Ne le trouvant pas, il renvoie un statut 404.
Renvoyer systématiquement index.html avec le code 200 pour toute route inconnue sur le disque.
La véritable page 404 de l'application est désormais gérée côté client par le routeur frontend (ex: path: '**').
# --- 1. NETLIFY (Fichier public/_redirects ou dist/_redirects) ---
/* /index.html 200
# --- 2. VERCEL (Fichier vercel.json à la racine du projet) ---
{
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
]
}
# --- 3. NGINX (Dans le bloc server { ... }) ---
location / {
try_files $uri $uri/ /index.html;
}
# --- 4. APACHE (Fichier .htaccess dans le dossier racine) ---
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>Imaginez une Single Page Application comme un livre unique :
/index.html). Quand vous cliquez sur "Contact", un petit robot JavaScript dans vos mains tourne la page pour vous et met une étiquette /contact sur votre front. Le serveur n'a jamais été contacté. contact.html sur le disque dur. Le bibliothécaire vous répond donc : 404 - Document introuvable !La règle de réécriture ordonne au serveur :
Le navigateur reçoit index.html, charge les bundles JavaScript React/Vue/Angular, et le routeur inspecte window.location.pathname : voyant /contact, il affiche le bon composant en une fraction de seconde !
Si un internaute tape une adresse qui n'existe vraiment pas dans votre application (ex: /page-inexistante-xyz), le serveur renvoie toujours index.html. C'est donc à votre routeur frontend d'intercepter ces cas via une route wildcard :
<Route
path="*"
element={<NotFound />}
/>{
path: '/:pathMatch(.*)*',
component: NotFound
}{
path: '**',
component: NotFoundComponent
}| Serveur / Hébergeur | Fichier de Configuration | Emplacement dans le Projet |
|---|---|---|
| Netlify | _redirects ou netlify.toml | Dossier de publication (public/ ou dist/) |
| Vercel | vercel.json | Racine du dépôt Git |
| Nginx (VPS / Dédié) | /etc/nginx/sites-available/default | Configuration système serveur (directive try_files) |
| Apache / Hébergement Mutualisé | .htaccess | Dossier racine public_html |
| Firebase Hosting | firebase.json | Racine du projet Firebase (section rewrites) |