Dans une application Laravel moderne utilisant Inertia.js et Vue.js, la gestion des erreurs et du mode maintenance peut être délicate.
Vous avez lancé un petit php artisan down pour mettre à jour votre application, et là, c'est le drame ? Au lieu de votre superbe page de maintenance personnalisée, vos visiteurs tombent sur un message tout moche "Service Unavailable" ou, pire, une page blanche ?
Pas de panique ! C'est un grand classique quand on utilise le combo Laravel 12 et Inertia.js. On dirait que ces deux-là ont parfois du mal à décider qui doit répondre en premier. Vous voulez savoir comment remettre de l'ordre dans tout ça ? C'est parti !
Dans ce guide, nous allons voir comment :
Comprendre pourquoi la page 503 ne s'affiche pas sur une stack Inertia.
Configurer l'ordre des middlewares pour éviter les conflits.
Personnaliser la page de maintenance pour qu'elle reste cohérente avec le design de votre app.
Gérer correctement le cycle de vie de la maintenance (
upetdown).
Prérequis : Pourquoi activer la maintenance ?
Avant de rentrer dans le code, rappelez-vous que le mode Maintenance (503) est indispensable pour la stabilité de votre application. Vous devez l'activer dans les situations suivantes :
Migrations de base de données lourdes : Lorsque vous modifiez la structure de la base (ajout de colonnes, changement de type de données), il est crucial d'arrêter l'accès pour éviter que les utilisateurs interagissent avec des tables qui sont en train d'être modifiées, ce qui causerait des erreurs critiques.
Mise à jour des dépendances (Composer) : Après un
composer updateoucomposer install, il est préférable de couper l'accès le temps que les fichiers de cache (Bootstrap, Config, Views) se régénèrent.Maintenance du serveur : Si vous redémarrez le serveur ou la base de données, vous devez activer le mode maintenance pour empêcher toute tentative de connexion pendant que les services reprennent.
Patchs de sécurité : Si vous devez corriger une faille critique, isolez votre site immédiatement en maintenance, appliquez le correctif, puis rétablissez le service.
En résumé : ne mettez jamais votre application en production en mode maintenance sans avoir une belle page 503 à afficher, sinon vos clients risquent de paniquer ou de penser que votre site a été piraté !
Le problème : Pourquoi ma page 503 ne s'affiche-t-elle pas ?
Ce problème vient très probablement de l'ordre d'exécution des middlewares dans votre fichier app/bootstrap/app.php.
Voici ce qui se passe en coulisses :
Lorsque vous lancez
php artisan down, Laravel active le middlewarePreventRequestsDuringMaintenance.Ce middleware doit normalement servir une page HTML brute (votre fichier
503.blade.php).Cependant, dans une application Inertia, le middleware
HandleInertiaRequeststente d'intercepter toutes les requêtes pour vérifier si c'est une requête AJAX (X-Inertia).Si
HandleInertiaRequestsest placé avant le middleware de maintenance, il va essayer d'intercepter la réponse, causant un conflit ou une page blanche, au lieu de laisser passer votre HTML simple.
La solution est donc de forcer Laravel à prioriser la maintenance sur Inertia.
Étape 1 : Publier les vues d'erreurs de Laravel
Assurez-vous que les fichiers de vues d'erreurs existent bien dans votre projet. Exécutez cette commande à la racine :
php artisan vendor:publish --tag=laravel-errorsÉtape 2 : Configurer l'ordre des Middlewares (La correction cruciale)
C'est ici que se situe la solution. Ouvrez votre fichier .app/bootstrap/app.php
Deux corrections sont nécessaires : 1
Importer la classe .
PreventRequestsDuringMaintenancePlacer ce middleware avant .
HandleInertiaRequests
Voici la version corrigée de :app/bootstrap/app.php
<?php
declare(strict_types=1);
use App\Http\Middleware\HandleAppearance;
use App\Http\Middleware\HandleInertiaRequests;
use App\Http\Middleware\RoleMiddleware;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets;
use Illuminate\Http\Request;
// CORRECTION 1 : Importer le middleware de maintenance
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance;
use Inertia\Inertia;
use Symfony\Component\HttpKernel\Exception\HttpException;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware): void {
$middleware->encryptCookies(except: ['appearance', 'sidebar_state']);
$middleware->alias([
'role' => RoleMiddleware::class,
]);
$middleware->web(append: [
// CORRECTION 2 : Ajouter le middleware de maintenance EN PREMIER
// Cela assure qu'il coupe l'accès avant qu'Inertia n'essaie de traiter la requête
PreventRequestsDuringMaintenance::class,
HandleAppearance::class,
HandleInertiaRequests::class,
AddLinkHeadersForPreloadedAssets::class,
]);
})
->withExceptions(function (Exceptions $exceptions): void {
// Intercepter toutes les exceptions HTTP pour les rendre avec Inertia
$exceptions->render(function (HttpException $e, Request $request) {
// Vérifier si la requête attend une réponse Inertia (XHR)
$inertiaRequest = $request->headers->get('X-Inertia');
// Si c'est une requête Inertia, renvoyer une réponse JSON avec le bon code d'erreur
if ($inertiaRequest) {
return response()->json([
'component' => 'Errors/Error',
'props' => [
'status' => $e->getStatusCode(),
],
'url' => $request->url(),
'version' => config('inertia.version'),
], $e->getStatusCode());
}
// Sinon, renvoyer une réponse Inertia normale
return Inertia::render('Errors/Error', [
'status' => $e->getStatusCode(),
])->toResponse($request)->setStatusCode($e->getStatusCode());
});
// Gérer spécifiquement l'erreur 404
$exceptions->render(function (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $e, Request $request) {
$inertiaRequest = $request->headers->get('X-Inertia');
if ($inertiaRequest) {
return response()->json([
'component' => 'Errors/Error',
'props' => [
'status' => 404,
],
'url' => $request->url(),
'version' => config('inertia.version'),
], 404);
}
return Inertia::render('Errors/Error', [
'status' => 404,
])->toResponse($request)->setStatusCode(404);
});
})->create();Étape
Maintenant que le routeur fonctionne, vous pouvez créer votre propre design. Créez ou modifiez le fichier `resources/viewsresources/views/errors/503.blade.php.
Voici un exemple de conception (utilisé par exemple pour informer un client que son système est en maintenance) utilisant le thème de couleurs de votre application :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Service en attente de mise à jour</title>
<style>
/* ... Insérez ici le CSS complet fourni dans votre prompt ... */
:root {
/* Mode Clair */
--background: hsl(330 100% 98.4314%);
--foreground: hsl(0, 0%, 0%);
--card: hsl(0 0% 100%);
--card-foreground: hsl(326.281 71.5976% 33.1373%);
--primary: #dc127b;
--primary-foreground: hsl(0 0% 100%);
--secondary: #f7b540;
--muted-foreground: hsl(329.0476 50% 50.5882%);
--border: hsl(326.7857 100% 89.0196%);
--font-sans: 'Poppins', sans-serif;
--radius: 0.75rem;
--shadow-md: 0px 3px 0px 0px hsl(330 70% 30% / 0.18), 0px 2px 4px -1px hsl(330 70% 30% / 0.18);
}
@media (prefers-color-scheme: dark) {
:root {
/* Mode Sombre */
--background: hsl(280.8 58.1395% 8.4314%);
--foreground: hsl(300 100% 85.098%);
--card: hsl(280 45.2055% 14.3137%);
--card-foreground: hsl(300 100% 85.098%);
--primary: #ef1184;
--primary-foreground: hsl(300 65.5172% 5.6863%);
--secondary: hsl(288.5106 42.3423% 21.7647%);
--muted-foreground: hsl(300 52.8736% 65.8824%);
--border: hsl(281.4706 55.7377% 23.9216%);
--font-sans: 'Quicksand', sans-serif;
--shadow-md: 0px 3px 0px 0px hsl(300 80% 50% / 0.18), 0px 2px 4px -1px hsl(300 80% 50% / 0.18);
}
}
body {
background-color: var(--background);
color: var(--foreground);
font-family: var(--font-sans);
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
padding: 20px;
box-sizing: border-box;
}
.card {
max-width: 550px;
width: 100%;
background: var(--card);
padding: 3.5rem 2.5rem;
border-radius: var(--radius);
border: 1px solid var(--border);
box-shadow: var(--shadow-md);
text-align: center;
}
h1 {
font-family: 'Playfair Display', serif;
color: var(--card-foreground);
font-size: 2.25rem;
margin-bottom: 1.5rem;
line-height: 1.2;
}
p {
color: var(--muted-foreground);
line-height: 1.8;
font-size: 1.1rem;
margin-bottom: 2.5rem;
}
strong {
color: var(--primary);
font-weight: 600;
}
.notice {
background: hsl(0 0% 0% / 0.04);
padding: 1rem;
border-radius: 0.5rem;
font-size: 0.9rem;
color: var(--muted-foreground);
border-left: 3px solid var(--secondary);
}
@media (max-width: 480px) {
.card { padding: 2rem 1.5rem; }
h1 { font-size: 1.75rem; }
}
</style>
</head>
<body>
<div class="card">
<h1>Service en attente de mise à jour</h1>
<p>
L'accès à la plateforme nécessite une <strong>actualisation administrative</strong>.
Pour garantir la continuité du service et retrouver l'intégralité des fonctionnalités, la régularisation de la situation est requise dès que possible.
</p>
<div class="notice">
Le service sera rétabli de façon automatique.
</div>
</div>
<script>
// Détection automatique du Dark Mode pour le visiteur
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
}
</script>
</body>
</html>Étape 4 : Activer le mode
Une fois les fichiers en place, nettoyez le cache pour être sûr que Laravel prend en compte les modifications de middlewares :
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clearPuis, activez le mode maintenance en ciblant votre vue personnalisée :
php artisan down --render="errors::503"Étape 5 : Désactiver la maintenance
Une fois vos mises à jour terminées :
php artisan upEt voilà ! Votre page personnalisée s'affiche enfin correctement, sans aucune interférence.
FAQ : Vos questions sur le mode maintenance
Pourquoi utiliser Blade pour la maintenance et pas Vue.js ? C'est une question de sécurité ! En mode maintenance, le moteur d'Inertia et de Vue peut être coupé. Blade est du HTML pur, c'est le moyen le plus fiable de s'assurer que quelque chose s'affiche, quoi qu'il arrive.
Est-ce que je peux voir mon site pendant que les autres voient la maintenance ? Bien sûr ! Utilisez php artisan down --secret="mon-code-secret". Vous pourrez y accéder via votre-site.com/mon-code-secret.
Comment sortir du mode maintenance ? C'est la commande la plus satisfaisante : php artisan up. Et hop, tout le monde revient !
Conclusion
Maîtriser le mode maintenance sous Laravel et Inertia n'est pas qu'une question de commande, c'est une question d'organisation. En remettant le middleware PreventRequestsDuringMaintenance à sa place (la première !), vous évitez bien des maux de tête.
Alors, prêt à mettre à jour votre application avec style ?
Souhaitez-vous que je vous aide à créer le composant Vue.js correspondant pour gérer vos erreurs 404 et 500 de manière élégante ?



