Module 1 – Introduction à Inertia.js
Niveau 5.2 – Laravel Inertia (React & Vue)
Objectif
À la fin de ce module, vous saurez :
- Ce qu’est Inertia.js et en quoi il diffère d’une SPA classique ou de Livewire.
- Quand choisir Inertia plutôt qu’une API REST + React/Vue ou qu’un stack 100 % Laravel (Blade/Livewire).
- Comment Laravel et React (ou Vue) travaillent ensemble : qui fait le routing, qui fournit les données, qui rend l’interface.
- Quel frontend choisir (React ou Vue) selon votre équipe et votre projet.
Ce module pose les bases conceptuelles ; les modules suivants entreront dans le code (Laravel, React et Vue) pas à pas.
Le problème que Inertia résout
Contexte
En développement web, on distingue souvent :
-
Applications « traditionnelles » : le serveur (PHP, Laravel) génère du HTML à chaque requête. Chaque clic sur un lien = nouvelle requête = nouvelle page HTML. C’est simple, mais chaque action peut provoquer un rechargement complet de la page (perte de scroll, flash blanc, sensation de lenteur).
-
Applications « SPA » (Single Page Application) : une seule page HTML est chargée une fois ; ensuite, c’est JavaScript (React, Vue, etc.) qui gère l’affichage et les données. Les données viennent d’une API (REST, GraphQL) appelée en AJAX. L’expérience est fluide, mais vous devez écrire et maintenir : les routes côté client, l’API côté serveur, l’authentification (tokens), la validation parfois en double (serveur + client), etc.
Inertia.js se place entre les deux : vous gardez les routes Laravel et la logique métier (validation, auth, Eloquent) côté serveur, mais l’interface est rendue par des composants React ou Vue. Il n’y a pas d’API REST à concevoir : Laravel envoie directement à React/Vue les données de la page sous forme de props. Résultat : une expérience « SPA » (navigation fluide, pas de rechargement complet) sans la complexité d’une API dédiée.
Détails techniques
- Inertia utilise des requêtes XHR avec un header
X-Inertia: true. Laravel détecte ce header et, au lieu de renvoyer du HTML, renvoie du JSON contenant le nom du composant de page et les props. Le client (React ou Vue) rend alors ce composant et met à jour le DOM (souvent via un simple remplacement du contenu principal). - En première visite (ou après un refresh), Laravel peut renvoyer du HTML complet : la page contient déjà le « shell » (layout) et les données de la page inline (en JSON dans un attribut
data-page). Le JavaScript Inertia hydrate l’app : il attache les écouteurs et prend le relais pour les navigations suivantes. Cela améliore le SEO et le temps de premier affichage.
Qu’est-ce qu’Inertia.js, concrètement ?
Inertia est une petite bibliothèque (côté Laravel + côté JavaScript) qui :
- Côté Laravel : vous utilisez
Inertia::render('NomDuComposant', [ ... props ... ])dans vos contrôleurs au lieu deview('blade.view', ...). Laravel envoie une réponse spéciale (JSON ou HTML avec données inline) que le client Inertia comprend. - Côté client (navigateur) : vous avez une app React ou Vue qui :
- intercepte les clics sur les liens et les soumissions de formulaires ;
- envoie des requêtes XHR vers Laravel ;
- reçoit le nom du composant + les props et rend ce composant à la place du contenu actuel.
Vous écrivez donc :
- Des routes Laravel (comme d’habitude).
- Des contrôleurs qui font la logique (requêtes BDD, validation, etc.) et renvoient
Inertia::render(...). - Des composants de page en React (fichiers
.jsx/.tsx) ou Vue (fichiers.vue) qui reçoivent les props et affichent l’UI.
Il n’y a pas de routeur React Router ou Vue Router à configurer pour les pages principales : c’est Laravel qui décide quelle « page » (composant) afficher selon l’URL.
Comparaison : SPA classique, Inertia, Livewire
Pour bien situer Inertia, voici trois façons de construire une app « moderne » avec Laravel.
1. SPA classique (Laravel API + React/Vue séparés)
| Aspect | Comment ça marche |
|---|---|
| Routing | Côté client (React Router, Vue Router). Les URLs sont gérées par le JS. |
| Données | Laravel expose une API REST (ou GraphQL). React/Vue appellent cette API (fetch, axios) et affichent les données. |
| Auth | Souvent tokens (JWT, Sanctum token) : le client envoie le token dans les requêtes API. |
| Validation | Côté serveur (Laravel) et souvent aussi côté client (pour un feedback immédiat). |
| Cas d’usage | Applications très découplées, équipes front/back séparées, ou besoin d’une API utilisée par plusieurs clients (web, mobile). |
Exemple (conceptuel) : une route Laravel GET /api/users renvoie du JSON ; en React vous faites fetch('/api/users') et vous affichez la liste. Vous devez gérer vous-même le chargement, les erreurs, la pagination côté client.
2. Inertia.js (Laravel + React ou Vue, une seule app)
| Aspect | Comment ça marche |
|---|---|
| Routing | Laravel (fichier routes/web.php). Une URL = une route Laravel. |
| Données | Le contrôleur Laravel prépare les données et les passe à Inertia::render('PageName', $props). React/Vue reçoivent ces props directement dans le composant de page. Pas d’API à appeler. |
| Auth | Session Laravel classique (cookies). Pas de JWT à gérer côté front. |
| Validation | 100 % Laravel. En cas d’erreur, Laravel redirige avec les erreurs ; Inertia les expose dans la page (objet errors). |
| Cas d’usage | Applications web modernes (UI React ou Vue) avec un seul backend Laravel, une seule codebase « full-stack », sans vouloir maintenir une API REST. |
Exemple (conceptuel) : une route Laravel GET /users appelle un contrôleur qui fait User::paginate(10) et Inertia::render('Users/Index', ['users' => $users]). Le composant React ou Vue Users/Index reçoit users en prop et l’affiche. Aucun fetch('/api/users') : les données arrivent avec la « page ».
3. Livewire (Laravel + Blade, pas de React/Vue)
| Aspect | Comment ça marche |
|---|---|
| Routing | Laravel. |
| Données & UI | Logique en PHP (composants Livewire), rendu en Blade (HTML). Les interactions (clic, formulaire) déclenchent des requêtes AJAX ; le serveur renvoie du HTML (ou des morceaux) et Livewire met à jour le DOM. |
| Cas d’usage | Back-offices, tableaux de bord, formulaires dynamiques quand on veut peu ou pas de JavaScript et tout garder en PHP/Blade. |
En résumé :
- Vous voulez React ou Vue (composants, écosystème npm, équipe front à l’aise avec JS) sans construire une API → Inertia.
- Vous voulez tout en Laravel (PHP + Blade), avec un peu de réactivité → Livewire.
- Vous avez besoin d’une API pour plusieurs clients ou équipes très séparées → SPA classique avec API Laravel.
React ou Vue avec Inertia ?
Inertia supporte officiellement React et Vue (Vue 3 recommandé). Le cours est rédigé pour les deux : chaque notion est illustrée en Laravel + React et en Laravel + Vue.
React
- Points forts : écosystème très riche (hooks, librairies), TypeScript bien intégré, beaucoup d’emplois et de ressources. Idéal si votre équipe connaît déjà React.
- Avec Inertia : vous écrivez des composants React (fonctions ou classes) ; les « pages » sont des composants qui reçoivent les props envoyées par Laravel. Vous pouvez utiliser tout l’écosystème React (état local, contextes, librairies UI).
Vue
- Points forts : syntaxe lisible (template, script, style), courbe d’apprentissage douce, excellente documentation. Souvent apprécié par des devs venant du PHP/Blade car le template ressemble un peu au HTML + directives.
- Avec Inertia : vous écrivez des composants Vue (fichiers
.vue) ; les pages reçoivent les props Laravel. Vous pouvez utiliser Composition API, Pinia, etc.
Conseil : choisir un des deux pour un projet et rester cohérent. Les concepts Inertia (routes Laravel, Inertia::render, props, liens, formulaires) sont identiques ; seul le code du composant change (syntaxe React vs Vue).
Flux détaillé d’une requête Inertia
Pour bien comprendre « qui fait quoi », voici le parcours d’une action utilisateur.
Scénario : l’utilisateur clique sur « Mes articles »
- Lien : dans votre interface, vous avez un lien (composant Link fourni par Inertia) vers
/articles(ouroute('articles.index')). - Clic : au lieu de faire un rechargement classique, Inertia intercepte le clic et envoie une requête XHR (XMLHttpRequest ou fetch) vers
GET /articles, avec un headerX-Inertia: trueet éventuellement d’autres headers (Accept, etc.). - Laravel : la route
GET /articlesest traitée par un contrôleur (ex.ArticleController@index). Le contrôleur fait sa logique (récupère les articles, pagination, etc.) puis appelle :return Inertia::render('Articles/Index', [
'articles' => $articles,
'filters' => $request->only('search'),
]); - Réponse : comme la requête contient
X-Inertia: true, Laravel ne renvoie pas du HTML, mais du JSON (ou une réponse spéciale) contenant par exemple :- le nom du composant à afficher :
"Articles/Index"; - les props :
{ articles: [...], filters: {...} }.
- le nom du composant à afficher :
- Client (navigateur) : le script Inertia (React ou Vue) reçoit cette réponse, résout le composant
Articles/Index(par exempleresources/js/Pages/Articles/Index.jsxou.vue), et rend ce composant en lui passant les props. Le DOM est mis à jour (souvent en remplaçant le contenu principal de la page), sans rechargement complet : la barre d’adresse affiche bien/articles, mais tout s’est fait en AJAX.
Première visite ou actualisation (F5)
Lorsque l’utilisateur ouvre l’URL directement (ou rafraîchit la page), la requête est une requête classique (pas XHR). Laravel renvoie alors une page HTML complète qui contient :
- le « shell » de l’application (layout avec la div racine, les scripts CSS/JS) ;
- les données de la page incluses dans le HTML (par exemple dans un attribut
data-pagesous forme JSON).
Le JavaScript Inertia se charge, lit ces données, rend le bon composant (ex. Articles/Index) avec les bonnes props, et « hydrate » l’app. Ensuite, les navigations se font en XHR comme décrit ci-dessus. Cela permet un bon référencement (le serveur envoie du HTML) et un premier affichage correct même si le JS met un peu de temps à charger.
Exemple minimal (pour fixer les idées)
Vous n’avez pas encore installé Inertia ; voici à quoi ressemble le flux en code, pour que vous voyiez la répartition des rôles.
Côté Laravel (route + contrôleur)
// routes/web.php
use App\Http\Controllers\HomeController;
Route::get('/', [HomeController::class, 'index']);
// app/Http/Controllers/HomeController.php
namespace App\Http\Controllers;
use Inertia\Inertia;
class HomeController extends Controller
{
public function index()
{
// Logique métier : on prépare les données
$featuredProducts = Product::where('featured', true)->take(4)->get();
// On envoie la « page » Inertia avec des props
return Inertia::render('Home', [
'featuredProducts' => $featuredProducts,
]);
}
}
Ici, Laravel décide quelle page afficher (Home) et quelles données lui passer. Pas d’API : les données sont directement dans l’appel à Inertia::render.
Côté React (composant de page)
// resources/js/Pages/Home.jsx
import React from 'react';
export default function Home({ featuredProducts }) {
return (
<div>
<h1>Bienvenue</h1>
<ul>
{featuredProducts.map((product) => (
<li key={product.id}>{product.name}</li>
))}
</ul>
</div>
);
}
Le composant reçoit featuredProducts en prop (fourni par Laravel) et l’affiche. Aucun useEffect ni fetch : les données sont déjà là.
Côté Vue (même page, autre syntaxe)
<!-- resources/js/Pages/Home.vue -->
<template>
<div>
<h1>Bienvenue</h1>
<ul>
<li v-for="product in featuredProducts" :key="product.id">
{{ product.name }}
</li>
</ul>
</div>
</template>
<script setup>
defineProps({
featuredProducts: {
type: Array,
required: true,
},
});
</script>
Même idée : Laravel envoie featuredProducts, Vue les affiche. La suite du cours détaille l’installation, les layouts, les formulaires, etc., toujours avec des exemples Laravel + React et Laravel + Vue.
À retenir
- Inertia = Laravel (routes, contrôleurs, validation, auth, Eloquent) + React ou Vue (UI uniquement). Pas d’API REST à concevoir.
- Une URL = une route Laravel qui renvoie
Inertia::render('Composant', [props]). Le composant React/Vue reçoit les props et affiche la page. - Navigation : liens et formulaires sont gérés par Inertia (XHR) ; pas de rechargement complet.
- React ou Vue : au choix ; le cours donne les deux. Choisir une stack et rester cohérent.
- Première visite / F5 : Laravel peut renvoyer du HTML avec les données inline ; Inertia hydrate l’app pour le SEO et le premier rendu.
Dans le prochain module, nous installons Laravel + Inertia + React (ou Vue) et nous créons la première page ensemble, pas à pas.