Les applications multi-pages (Multi-Page-Applications ou MPA) perdent de leur popularité de jour en jour. Des plateformes célèbres comme Facebook, Twitter, YouTube, Github et bien d’autres utilisent déjà la technologie des applications mono-pages (Single-Page-Application ou SPA) à la place.

Cette technologie à la mode permet aux utilisateurs de s’engager avec les applications web de manière rapide et réactive car tout est rendu côté client. Cependant, elle peut s’avérer pénible pour les développeurs qui construisent des applications rendues côté serveur avec des frameworks comme Laravel ou Django.

Heureusement, Inertia.js est intervenu et est venu à la rescousse.

Dans cet article, nous allons vous montrer comment vous pouvez commencer à utiliser Inertia.js et comment l’utiliser avec Laravel, Vue.js et Tailwind CSS pour créer une application web de blog moderne. Nous partagerons également la façon de rendre les SPA plus conviviales pour le SEO, ainsi que quelques autres astuces.

Si vous débutez avec Laravel, nous vous recommandons de lire d’abord cet article pour être prêt à démarrer.

Pourquoi SPA ?

Avant de demander pourquoi nous devrions utiliser Inertia, nous devons d’abord nous demander : « Pourquoi SPA ? »

Pourquoi préférerait-on les applications rendues côté client aux applications traditionnelles côté serveur ? Qu’est-ce qui forcerait un développeur Laravel full-stack à dire adieu aux blade componets ?

La réponse courte : parce que la vitesse et la réactivité sont essentielles à tout engagement réussi de l’utilisateur.

Dans le cas des AMP, le navigateur envoie constamment des requêtes au backend, qui exécute ensuite de nombreuses requêtes de base de données. Une fois que la base de données et le serveur ont traité les requêtes et les ont transmises au navigateur, la page est rendue.

Mais les SPA sont différents. L’application apporte tout ce dont l’utilisateur a besoin directement sur la page, éliminant ainsi la nécessité pour le navigateur d’envoyer des requêtes ou de recharger la page pour rendre de nouveaux éléments HTML.

En raison de cette expérience utilisateur unique, de nombreuses entreprises de renom réclament que leurs sites web deviennent des applications à page unique.

Cela dit, la création d’une application à page unique peut être difficile pour les développeurs Laravel, car elle les obligerait à commencer à utiliser Vue.js ou React au lieu des modèles de lame, ce qui entrainerait la perte de nombreux joyaux Laravel qui permettent d’économiser du temps et des efforts.

Mais maintenant que nous avons Inertia.js, tout cela a changé.

Pourquoi Inertia ?

Si les développeurs Laravel devaient construire des SPA web avec Vue avant Inertia, ils devaient configurer des API et renvoyer des données JSON avec Laravel, puis utiliser quelque chose comme AXIOS pour récupérer les données dans les composants Vue. Ils auraient également besoin de quelque chose comme Vue Router pour gérer les routes, ce qui signifierait perdre le routage Laravel, ainsi que les middlewares et les contrôleurs.

Inertia.js, en revanche, permet aux développeurs de construire des applications modernes à page unique Vue, React et Svelte en utilisant un routage et des contrôleurs classiques côté serveur. Inertia a été conçu pour les développeurs de Laravel, Ruby on Rails et Django afin de leur permettre de créer des applications sans modifier leurs techniques de codage consistant à créer des contrôleurs, à extraire des données d’une base de données et à rendre des vues

Grâce à Inertia.js, les développeurs Laravel se sentiront comme chez eux.

Comment fonctionne Inertia ?

Construire un SPA uniquement avec Laravel et Vue vous donnera une page JavaScript complète pour votre interface publique, mais cela ne vous fournira pas une expérience d’application à page unique. Chaque lien cliqué entrainera le redémarrage de votre framework côté client au chargement de la page suivante.

C’est là qu’Inertia entre en jeu.

Inertia est essentiellement une bibliothèque de routage côté client. Elle vous permet de naviguer entre les pages sans avoir à recharger la page entière. Ceci est réalisé par le biais du composant <Link>, qui est une enveloppe légère autour d’une balise d’ancrage standard.

Lorsque vous cliquez sur un lien Inertia, Inertia intercepte le clic et vous redirige vers XHR à la place. Le navigateur ne rechargera pas la page de cette façon, offrant ainsi à l’utilisateur une expérience complète de page unique.

Démarrer avec Inertia

Un exemple de page réalisée avec Inertia.js
Un exemple de page réalisée avec Inertia.js

Pour comprendre Inertia et comment l’intégrer à Laravel, nous allons construire une application web de blog nommée Kinsta Blog en utilisant le combo le plus puissant, Laravel pour le backend, Vue.js pour le frontend JavaScript et Tailwind CSS pour le styling.

Si vous préférez suivre ce tutoriel dans un environnement local, vous pouvez utiliser DevKinsta, un outil puissant pour les développeurs, les concepteurs et les agences qui leur permet de construire des applications web WordPress à une ou plusieurs pages. Heureusement, WordPress peut être facilement intégré à Laravel à l’aide du package Corcel.

Conditions préalables

Pour tirer le meilleur parti de ce tutoriel, vous devez être familiarisé avec les éléments suivants :

  • Bases de Laravel (installation, base de données, migrations de bases de données, Eloquent Models, contrôleurs et routage)
  • Bases de Vue.js (installation, structure, et formulaires)

Si vous n’êtes pas sûr de vous, consultez ces fantastiques tutoriels gratuits et payants sur Laravel. Sinon, lançons-nous.

Étape 1 : installer les éléments de base

Pour vous concentrer sur Inertia.js et passer directement à la partie amusante, assurez-vous d’avoir la configuration suivante prête à fonctionner :

  1. Projet Laravel 9 fraichement installé nommé kinsta-blog
  2. Tailwind CSS CLI installé dans notre projet Laravel
  3. Fichier image « kinsta-logo.png ». Téléchargez et décompressez le pack de logos Kinsta depuis Presse Archive et copiez kinsta-logo2.png dans le répertoire public/images sous le nom de kinsta-logo.png.
  4. Deux composants lame dans kinsta-blog/resources/views pour afficher la page d’accueil du blog et un seul article sur le blog comme indiqué ci-dessous : « /resources/views/index.blade.php » :
    <!DOCTYPE html>
    <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    
        <title>Kinsta Blog</title>
      </head>
    
      <body>
        <header>
          <h1>Kinsta Blog</h1>
        </header>
    
        <main>
          <h2>Read our latest articles</h2>
    
          <section>
            <article>
              <div>
                <img src="/images/kinsta-logo.png" alt="Article thumbnail" />
              </div>
    
              <h3>Title for the blog</h3>
              <p>
                Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illum rem
                itaque error vel perferendis aliquam numquam dignissimos, expedita
                perspiciatis consectetur!
              </p>
    
              <a href="#">Read more</a>
            </article>
          </section>
        </main>
    
        <footer>
          <h2>Join our Newsletter</h2>
    
          <input type="email" />
        </footer>
      </body>
    </html>

    « /resources/views/show.blade.php » :

    <!DOCTYPE html>
    <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    
        <title>Kinsta Blog</title>
      </head>
    
      <body>
        <main>
          <article>
            <div>
              <img src="/images/kinsta-logo.png" alt="Article thumbnail" />
            </div>
    
            <h1>Title for the blog</h1>
    
            <p>Article content goes here</p>
          </article>
        </main>
    
        <footer>
          <h2>Join our Newsletter</h2>
    
          <input type="email" />
        </footer>
      </body>
    </html>
  5. Base de données locale MySQL nommée kinsta_blog connectée à notre projet : « .env » :
    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=kinsta_blog
    DB_USERNAME=root
    DB_PASSWORD=
  6. Modèle d’article, migrations et fabriques : «  app/Models/Article.php » :
    <?php
    
    namespace AppModels;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    
    class Article extends Model
    {
        use HasFactory;
    
        protected $fillable = ['title', 'excerpt', 'body'];
    }

    « database/migrations/create_articles_table.php » :

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    
    return new class extends Migration
    {
    
        public function up()
        {
            Schema::create('articles', function (Blueprint $table) {
                $table->id();
                $table->string('title');
                $table->text('excerpt');
                $table->text('body');
                $table->timestamps();
            });
        }
    
        public function down()
        {
            Schema::dropIfExists('articles');
        }
    };

    « database/factories/ArticleFactory.php » :

    <?php
    
    namespace DatabaseFactories;
    
    use Illuminate\Database\Eloquent\Factories\Factory;
    
    class ArticleFactory extends Factory
    {
    
        public function definition()
        {
            return [
                'title' => $this->faker->sentence(6),
                'excerpt' => $this->faker->paragraph(4),
                'body' => $this->faker->paragraph(15),
            ];
        }
    }

C’est tout ce dont nous avons besoin pour commencer ! Passons maintenant aux choses sérieuses et introduisons Inertia.js dans notre projet.

Étape 2 : Installer Inertia

Le processus d’installation d’Inertia est divisé en deux grandes phases : côté serveur (Laravel) et côté client (VueJs).

Le guide d’installation officiel dans la documentation d’Inertia est un peu dépassé car Laravel 9 utilise désormais Vue par défaut, mais nous allons le parcourir également.

1. Côté serveur

La première chose que nous devons faire est d’installer les adaptateurs Inertia côté serveur avec la commande terminal ci-dessous via Composer.

composer require inertiajs/inertia-laravel

Maintenant, nous allons configurer notre modèle racine, qui sera un fichier lame unique qui sera utilisé pour charger vos fichiers CSS et JS, ainsi qu’une racine Inertia qui sera utilisée pour lancer notre application JavaScript.

Comme nous utilisons la version la plus récente de Laravel 9 v9.3.1, nous devons également permettre à Vite de faire fonctionner sa magie en l’incluant dans nos balises dans /resources/views/app.blade.php :

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <!-- Fetch project name dynamically -->
    <title inertia>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    @vite('resources/js/app.js') @inertiaHead
  </head>

  <body class="font-sans antialiased">
    @inertia
  </body>
</html>

Remarquez comment nous sommes capables de récupérer le titre du projet de manière dynamique en ajoutant l’attribut inertia aux balises <title>.

Nous avons également ajouté la directive @vite à l’en-tête afin de faire connaître à Vite le chemin de notre fichier principal JavaScript où nous avons créé notre application et importé notre CSS. Vite est un outil qui facilite le développement JavaScript et CSS en permettant aux développeurs de visualiser les modifications apportées au frontend sans avoir à actualiser la page pendant le développement local.

Notre prochaine étape sera de créer le middleware HandleInertiaRequests et de le publier dans notre projet. Nous pouvons le faire en lançant la commande de terminal ci-dessous dans le répertoire racine de notre projet :

php artisan inertia:middleware

Une fois cette opération terminée, rendez-vous dans « App/Http/Kernel.php » et enregistrez HandleInertiaRequests comme dernier élément de vos middlewares web :

'web' => [
    // ...
    App\Http\Middleware\HandleInertiaRequests::class,
],

2. Côté client

Ensuite, nous devons installer les dépendances de notre frontend Vue.js 3 de la même manière que du côté serveur :

npm install @inertiajs/inertia @inertiajs/inertia-vue3
// or
yarn add @inertiajs/inertia @inertiajs/inertia-vue3

Ensuite, vous devez installer Vue.js 3 :

npm install vue@next

Puis mettez à jour votre fichier JavaScript principal pour initialiser Inertia.js avec Vue.js 3, Vite et Laravel :

« resources/js/app.js » :

import "./bootstrap";
import "../css/app.css";

import { createApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/inertia-vue3";
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";

createInertiaApp({
  title: (title) => `${title} - ${appName}`,
  resolve: (name) =>
    resolvePageComponent(
      `./Pages/${name}.vue`,
      import.meta.glob("./Pages/**/*.vue")
    ),
  setup({ el, app, props, plugin }) {
    return createApp({ render: () => h(app, props) })
      .use(plugin)
      .mount(el);
  },
});

Dans l’extrait de code ci-dessus, nous utilisons le plugin resolvePageComponent de Laravel, et nous lui demandons de résoudre nos composants à partir du répertoire ./Pages/$name.vue. En effet, nous enregistrerons nos composants Inertia dans ce répertoire plus tard dans notre projet, et cette extension nous aidera à charger automatiquement ces composants depuis le bon répertoire.

Tout ce qui reste à faire est d’installer vitejs/plugin-vue:

npm i @vitejs/plugin-vue

Et mettre à jour le fichier vite.config.js file :

import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [
    laravel({
      input: ["resources/css/app.css", "resources/js/app.js"],
      refresh: true,
    }),
    vue({
      template: {
        transformAssetUrls: {
          base: null,
          includeAbsolute: false,
        },
      },
    }),
  ],
});

L’étape finale consiste à installer nos dépendances et à compiler nos fichiers :

npm install

npm run dev

Et voilà ! Vous vous êtes procuré une application Laravel 9 fonctionnelle avec Vue.js 3 et Vite. Maintenant, nous devons voir quelque chose en action !

Création de pages Inertia

Vous vous souvenez de ces deux fichiers blade (index et show) pour afficher notre page d’accueil et un seul article ?

Le seul fichier blade dont nous aurons besoin en utilisant Inertia est app.blade.php, que nous avons déjà utilisé une fois lors de l’installation d’Inertia. Alors qu’advient-il de ces fichiers maintenant ?

Nous allons transformer ces fichiers de composants blade en composants Inertia.js.

Chaque page de votre application possède son propre contrôleur et composant JavaScript avec Inertia. Cela vous permet d’obtenir uniquement les données requises pour cette page, sans utiliser une API. Les pages Inertia ne sont rien d’autre que des composants JavaScript, dans notre cas, ce sont des composants Vue.js. Elles n’ont rien de particulièrement remarquable à leur sujet. Donc, ce que nous allons faire, c’est envelopper tout le contenu HTML entre les balises <template> et tout ce qui est lié à JavaScript sera enveloppé avec les balises <script>.

Créez un dossier appelé « Pages » et déplacez-y vos fichiers. Nous aurons donc « index.blade.php » et « show.blade.php » dans « ./resources/js/Pages ». Ensuite, nous modifierons le format du fichier en « .vue » au lieu de « .blade.php » tout en mettant la première lettre de leurs noms en majuscule et nous transformerons son contenu en un composant Vue.js standard. Nous exclurons les balises <html>, <head>, et <body> car elles sont déjà incluses dans le composant racine principal de la lame.

« resources/js/Pages/Index.vue » :

<script setup>
  //
</script>

<template>
  <header>
    <h1>Kinsta Blog</h1>
  </header>

  <main>
    <h2>Read our latest articles</h2>

    <section>
      <article>
        <div>
          <img src="/images/kinsta-logo.png" alt="Article thumbnail" />
        </div>

        <h3>Title for the blog</h3>
        <p>
          Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illum rem
          itaque error vel perferendis aliquam numquam dignissimos, expedita
          perspiciatis consectetur!
        </p>

        <a href="#">Read more</a>
      </article>
    </section>
  </main>

  <footer>
    <h2>Join our Newsletter</h2>

    <input type="email" />
  </footer>
</template>

« resources/js/Pages/Show.vue » :

<script setup>
  //
</script>

<template>
  <header>
    <h1>Welcome to Kinsta Blog</h1>
  </header>

  <main>
    <article>
      <h1>Title for the blog</h1>

      <p>Article content goes here</p>
    </article>
  </main>

  <footer>
    <h2>Join our Newsletter</h2>

    <input type="email" />
  </footer>
</template>

Il y a quelque chose qui me dérange vraiment ! Nous continuons à copier et coller notre en-tête et notre pied de page dans chaque composant, ce qui n’est pas une très bonne pratique. Créons un Layout de base Inertia pour stocker nos composants persistants.

Créez un dossier appelé « Layouts » dans « /resources/js » et dans ce dossier, créez un fichier nommé « KinstaLayout.vue ». Ce fichier contiendra notre en-tête et notre pied de page et le main avec un <slot /> pour permettre à tous les composants enveloppés avec cette mise en page d’être intégrés à l’intérieur. Ce fichier devrait ressembler à ceci :

« resources/js/Layouts/KinstaLayout.vue » :

<script setup></script>

<template>
    <header>
    <h1>Kinsta Blog</h1>
  </header>

  <main>
        <slot />
  </main>

  <footer>
    <h2>Join our Newsletter</h2>

    <input type="email" />
  </footer>

</template>

Ensuite, nous allons importer cette nouvelle mise en page dans nos pages et envelopper tout le contenu HTML avec elle. Nos composants devraient ressembler à ceci :

Index.vue:

<script setup>
import KinstaLayout from "../Layouts/KinstaLayout.vue";
</script>

<template>
  <KinstaLayout>
    <section>
      <h2>Read our latest articles</h2>
      <article>
        <div>
          <img src="/images/kinsta-logo.png" alt="Article thumbnail" />
        </div>

        <h3>Title for the blog</h3>
        <p>
          Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illum rem
          itaque error vel perferendis aliquam numquam dignissimos, expedita
          perspiciatis consectetur!
        </p>

        <a href="#">Read more</a>
      </article>
    </section>
  </KinstaLayout>
 </template>

Show.vue:

<script setup>
 import KinstaLayout from "../Layouts/KinstaLayout.vue";
</script>

<template>
  <KinstaLayout>
    <article>
      <h1>Title for the blog</h1>

      <p>Article content goes here</p>
    </article>
  </KinstaLayout>
</template>

Routes Laravel et rendu Inertia

Tout d’abord, utilisons le fichier « ArticleFactory » que nous avons depuis le point de départ de notre tutoriel et semons quelques articles dans notre base de données.

« database/seeders/databaseSeeder.php » :

<?php

namespace Database\Seeders;

use App\Models\Article;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        Article::factory(10)->create();
    }
}

Ensuite, saisissez la commande terminal ci-dessous pour migrer vos tables et ensemencer les fausses données des usines :

php artisan migrate:fresh --seed

Ceci créera 10 faux articles dans la base de données, que nous devrons passer à notre vue en utilisant le routage Laravel. Maintenant que nous utilisons Inertia pour rendre les vues, la façon dont nous écrivions nos routes va légèrement changer. Créons notre première route Laravel Inertia dans « routes/web.php » et renvoyons la vue de la page d’accueil depuis « /resources/js/Pages/Index.vue ».

« routes/web.php » :

<?php

use App\Models\Article;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;

Route::get('/', function () {
    return Inertia::render('Index', [
        'articles' => Article::latest()->get()
    ]);
})->name('home');

Remarquez que nous avons importé Inertia et que nous n’avons pas utilisé l’aide Laravel view() pour retourner la vue, mais plutôt Inertia::render. Inertia recherchera également par défaut le nom du fichier que nous avons mentionné dans notre route dans le dossier Pages à « resources/js ».

Dirigez-vous vers le fichier d’Index et définissez les données récupérées en tant que prop et bouclez sur elles avec v-for pour afficher les résultats. Entre les balises de script, définissez les données passées en tant qu’accessoire. Tout ce qu’Inertia doit savoir est le type de données que vous attendez, qui dans notre cas est un objet ‘Article’ contenant un tableau d’articles.

« resources/js/Pages/Index.vue » :

<script setup>
import KinstaLayout from "../Layouts/KinstaLayout.vue";

  defineProps({
    articles: Object,
  });
</script>

Notez qu’il suffit de le définir comme prop sans le renvoyer car nous utilisons le format setup pour l’API de composition de Vue.js 3. Si nous utilisions l’API d’options, nous devrions le renvoyer.

Faisons la boucle :

<template>
  <KinstaLayout>
    <h2>Read our latest articles</h2>

    <section>
      // Looping over articles
      <article v-for="article in articles":key="article.id">
        <div>
          <img src="/images/kinsta-logo.png" alt="Article thumbnail" />
        </div>

        <h3>{{article.title}}</h3>
        <p>{{article.excerpt}}</p>

        <a href="#">Read more</a>
      </article>
    </section>
  </KinstaLayout>
</template>

npm run dev (laissez-la en cours d’exécution car nous utilisons Vite) et php artisan serve pour démarrer le serveur de développement laravel et accéder à notre site web, nous verrons la page attendue affichant les dix articles de la base de données.

Maintenant, nous utilisons l’extension Vue DevTools de Google Chrome, qui nous permet de déboguer mon application. Nous allons vous montrer comment nos données sont transmises au composant.

Inspecter les propriétés.
Inspecter les propriétés.

« articles » est transmis au composant en tant qu’objet prop contenant un tableau d’articles ; chaque article du tableau est également un objet avec des propriétés qui correspondent aux données qu’il a acquises de la base de données. Cela signifie que toute donnée que nous transférons de Laravel à Inertia sera traitée comme un objet prop.

Utilisation de Tailwind CSS avec Inertia.js

Puisque Tailwind est déjà installé dans notre projet au point de départ, tout ce que nous devons faire est de lui dire de lire nos composants Inertia. Ceci peut être accompli en modifiant « tailwind.config.js » comme ci-dessous :

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./storage/framework/views/*.php",
    "./resources/views/**/*.blade.php",
    "./resources/js/**/*.vue",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

Assurez-vous ensuite que nous avons importé notre fichier CSS dans « resources/js/app.js » :

import "../css/app.css";

Et maintenant nous sommes prêts à styliser nos composants.

« resources/js/Pages/Index.vue » :

<script setup>
import KinstaLayout from "../Layouts/KinstaLayout.vue";

  defineProps({
    articles: Object,
  });
</script>

<template>
 <KinstaLayout>
    <h2 class="text-2xl font-bold py-10">Read our latest articles</h2>

    <section class="space-y-5 border-b-2 pb-10">
      <article
        v-for="article in articles"
        :key="article.id"
        class="flex justify-center items-center shadow-md bg-white rounded-xl p-4 mx-auto max-w-3xl"
      >

         <img
            src="/images/kinsta-logo.png"
            class="w-32 h-32 rounded-xl object-cover"
            alt=""
         />

        <div class="flex flex-col text-left justify-between pl-3 space-y-5">
          <h3
            class="text-xl font-semibold text-indigo-600 hover:text-indigo-800"
          >
            <a href="#">{{ article.title }}</a>
          </h3>
          <p>
           {{ article.excerpt }}
          </p>
          <a
            href="#"
            class="text-indigo-600 hover:text-indigo-800 w-fit self-end font-semibold"
            >Read more</a
          >
        </div>
      </article>
    </section>
 </KinstaLayout>
</template>

« resources/js/Layouts/KinstaLayout.vue » :

<script setup></script>

<template>
    <header
        class="bg-gradient-to-r from-blue-700 via-indigo-700 to-blue-700 w-full text-center py-4"
    >
        <h1 class="text-white font-bold text-4xl">Kinsta Blog</h1>
    </header>

    <main class="container mx-auto text-center">
        <slot />
    </main>

    <footer
        class="bg-gradient-to-b from-transparent to-gray-300 w-full text-center mt-5 py-10 mx-auto"
    >
        <h2 class="font-bold text-xl pb-5">Join our Newsletter</h2>

        <input
            class="rounded-xl w-80 h-12 px-3 py-2 shadow-md"
            type="email"
            placeholder="Write your email.."
        />
    </footer>
</template>

Si vous regardez le navigateur, vous remarquerez que Vite a déjà mis à jour la page avec la magie de Tailwind.

Rendu des propriétés Inertia.
Rendu des propriétés Inertia.

Liens Inertia

Maintenant que nous avons une page d’accueil fonctionnelle qui peut afficher tous les articles de la base de données, nous devons créer une autre route pour afficher les articles individuels. Créons une nouvelle route et définissons l’URL avec un caractère générique « id » :

« routes/web.php »

<?php

use App\Models\Article;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;

Route::get('/', function () {
    return Inertia::render('Index', [
        'articles' => Article::latest()->get()
    ]);
})->name('home');

Route::get('/posts/{article:id}', function (Article $article) {
    return Inertia::render('Show', [
        'article' => $article
    ]);
})->name('article.show');

Nous avons importé le modèle « Article » et ajouté une nouvelle route pour renvoyer le composant Inertia Show.vue. Nous avons également tiré parti de la liaison de modèle de route de Laravel, qui permet à Laravel d’obtenir automatiquement l’article auquel nous faisons référence.

Tout ce dont nous avons besoin maintenant, c’est d’un moyen de visiter cette route en cliquant sur un lien de la page d’accueil sans avoir à recharger la page entière. Ceci est possible grâce à l’outil magique d’Inertia <Link>. Nous avons mentionné dans l’introduction qu’Inertia utilise <Link> comme enveloppe pour une balise d’ancrage standard <a>, et que cette enveloppe est destinée à rendre les visites de pages aussi transparentes que possible. Dans Inertia, la balise <Link> peut se comporter comme une balise d’ancrage qui exécute les requêtes <GET>, mais elle peut aussi agir comme une <button> et une <form> en même temps. Voyons comment nous pouvons l’appliquer à notre projet.

Dans notre Index.vue, nous allons importer <Link> d’Inertia, et supprimer les balises d’ancrage <a> et les remplacer par des balises Inertia <Link>. L’attribut href sera défini sur l’URL de la route que nous avons précédemment créée pour la consultation de l’article :

<script setup>
import KinstaLayout from "../Layouts/KinstaLayout.vue";
import { Link } from "@inertiajs/inertia-vue3";

defineProps({
    articles: Object,
});
</script>

<template>
    <KinstaLayout>
        <section class="space-y-5 border-b-2 pb-10">
            <h2 class="text-2xl font-bold pt-10 mx-auto text-center">
                Read our latest articles
            </h2>

            <article
                v-for="article in articles"
                :key="article.id"
                class="flex justify-center items-center shadow-md bg-white rounded-xl p-4 mx-auto max-w-3xl"
            >
                <img
                    src="/images/kinsta-logo.png"
                    class="w-32 h-32 rounded-xl object-cover"
                    alt=""
                />

                <div
                    class="flex flex-col text-left justify-between pl-3 space-y-5"
                >
                    <h3
                        class="text-xl font-semibold text-indigo-600 hover:text-indigo-800"
                    >
                        <Link :href="'/posts/' + article.id">{{
                            article.title
                        }}</Link>
                    </h3>
                    <p>
                        {{ article.excerpt }}
                    </p>
                    <Link
                        :href="'/posts/' + article.id"
                        class="text-indigo-600 hover:text-indigo-800 w-fit self-end font-semibold"
                        >Read more
                    </Link>
                </div>
            </article>
        </section>
    </KinstaLayout>
</template>

Nous allons styliser Show.vue avec Tailwind pour qu’il ait l’air un peu plus habillé et prêt pour notre visite. Nous devons également lui faire savoir qu’il doit s’attendre à un objet « Article » et le définir en tant qu’accessoire :

<script setup>
import KinstaLayout from "../Layouts/KinstaLayout.vue";

defineProps({
    article: Object,
});
</script>

<template>
    <KinstaLayout>
        <article class="mx-auto mt-10 flex justify-center max-w-5xl border-b-2">
            <img
                src="/images/kinsta-logo.png"
                class="w-80 h-80 rounded-xl mx-auto py-5"
                alt=""
            />
            <div class="text-left flex flex-col pt-5 pb-10 px-10">
                <h1 class="text-xl font-semibold mb-10">{{ article.title }}</h1>
                <p>{{ article.body }}</p>
            </div>
        </article>
    </KinstaLayout>
</template>

Maintenant, lorsque nous cliquons sur le titre de l’article ou sur « Read more », nous serons magiquement transportés vers Show.vue sans rafraîchir la page.

Les liens d'inertie sont en place
Les liens d’inertie sont en place.

Dans notre cas, nous utilisons <Link> comme balise d’ancrage qui envoie une requête GET à la route et renvoie les nouvelles données, mais nous pouvons utiliser <Link> pour également POST, PUT, PATCH et DELETE

« routes/web.php » :

<Link href="/logout" method="post" as="button" type="button">Logout</Link>

Trucs et astuces de Laravel Inertia que vous devriez connaître

Nous avons maintenant un SPA fonctionnel construit avec Laravel, Inertia et Tailwind CSS. Mais Inertia peut nous aider à réaliser bien plus. Il est temps d’acquérir quelques techniques Inertia qui aideront à la fois les développeurs et les visiteurs de l’application.

Générer des URL

Vous avez peut-être remarqué que nous avons ajouté des noms à nos routes Laravel sans les utiliser. Inertia nous permet d’utiliser nos routes nommées dans nos composants au lieu d’écrire manuellement la route complète.

Nous pouvons y parvenir en installant le paquetage Ziggy dans notre projet :

composer require tightenco/ziggy

Ensuite, allez dans « resources/js/app.js » et mettez-le à jour comme ceci :

import "./bootstrap";
import "../css/app.css";

import { createApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/inertia-vue3";
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";
import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m";

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) =>
        resolvePageComponent(
            `./Pages/${name}.vue`,
            import.meta.glob("./Pages/**/*.vue")
        ),
    setup({ el, app, props, plugin }) {
        return createApp({ render: () => h(app, props) })
            .use(plugin)
            .use(ZiggyVue, Ziggy)
            .mount(el);
    },
});

Allez dans « /resources/views/app.blade.php » et mettez à jour le head avec la directive @routes:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Fetch project name dynamically -->
    <title inertia>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    @routes
    @vite('resources/js/app.js')
    @inertiaHead
</head>

<body class="font-sans antialiased">
    @inertia
</body>

</html>

…et rafraîchissez vos paquets NPM en tapant les deux commandes de terminal ci-dessous :

npm install && npm run dev

Ce paquetage nous permet d’utiliser des routes nommées dans nos composants Inertia. Dirigeons-nous donc vers Index.vue et supprimons l’ancienne route manuelle pour la remplacer par le nom de la route tout en transmettant les données normalement comme si nous étions dans notre contrôleur.

Nous allons remplacer ceci :

<Link :href="'/posts/' + article.id">
   {{ article.title }}
</Link>

…par ceci :

<Link :href="route('article.show', article.id)">
   {{ article.title }}
</Link>

Cela nous donnera exactement le même comportement que nous avions, mais c’est plus convivial pour les développeurs et extrêmement utile lorsque votre itinéraire attend de nombreux paramètres.

Indicateurs de progression

Il s’agit de l’une des caractéristiques les plus intéressantes d’Inertia.js ; étant donné que les SPA offrent une expérience interactive à l’utilisateur, le fait d’avoir un retour constant sur le chargement d’une requête serait un ajout fantastique à l’application. Ceci peut être accompli par une bibliothèque séparée qu’Inertia offre.

La bibliothèque « @inertiajs/progress » est une enveloppe autour de NProgress qui affiche conditionnellement les indicateurs de chargement en fonction des événements Inertia. Vous n’avez pas vraiment besoin de savoir comment cela fonctionne dans les coulisses, alors faisons en sorte que cela fonctionne.

Nous pouvons installer cette bibliothèque avec la commande de terminal ci-dessous :

npm install @inertiajs/progress

Une fois installée, nous devons l’importer dans « resources/js/app.js »

import "./bootstrap";
import "../css/app.css";

import { createApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/inertia-vue3";
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";
import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m";
import { InertiaProgress } from "@inertiajs/progress";

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) =>
        resolvePageComponent(
            `./Pages/${name}.vue`,
            import.meta.glob("./Pages/**/*.vue")
        ),
    setup({ el, app, props, plugin }) {
        return createApp({ render: () => h(app, props) })
            .use(plugin)
            .use(ZiggyVue, Ziggy)
            .mount(el);
    },
});

InertiaProgress.init({ color: "#000000", showSpinner: true });

Cela affichera une barre de chargement et un spinner de chargement en couleur noire, mais nous pouvons changer la couleur ainsi que d’autres options utiles qui se trouvent dans la documentation de l’indicateur de progression Inertia.js.

L'indicateur de progression Inertia (en haut à droite).
L’indicateur de progression Inertia (en haut à droite).

Gestion du défilement

Dans certains cas, vous pouvez souhaiter naviguer vers une nouvelle page tout en conservant la même position de défilement. Vous en aurez peut-être besoin si vous permettez aux utilisateurs de laisser des commentaires ; cela soumettra un formulaire et chargera le nouveau commentaire de la base de données dans votre composant ; vous voudrez que cela se produise sans que l’utilisateur perde la position de défilement. Inertia s’en charge pour nous.

Dans notre cas, appliquons-la à notre balise <Link> dans Index.vue. Pour préserver la position de défilement tout en redirigeant vers une page différente avec <Link> d’Inertia, il suffit d’ajouter l’attribut preserve-scroll à <Link>:

<Link :href="route('article.show', article.id)" preserve-scroll>
  {{ article.title }}
</Link>

Conseils SEO

Depuis la naissance des SPA, les gens se préoccupent de l’optimisation des moteurs de recherche (SEO). Il est communément admis que si vous utilisez l’approche SPA, les moteurs de recherche auront du mal à explorer votre application web car tout est rendu côté client, ce qui fait que votre site n’apparaîtra pas en tête des résultats de recherche. Néanmoins, comment se fait-il que ces plateformes populaires comme Facebook et Github sont maintenant des SPA et obtiennent toujours de bons résultats en matière de SEO ?

Eh bien, ce n’est plus une mission : impossible. Inertia propose quelques solutions pour aider votre SPA à devenir SEO friendly.

Inertia Vue SSR avec Laravel et Vite

Les moteurs de recherche recherchent toujours du HTML sur votre site web afin d’en identifier le contenu ; cependant, si vous n’avez pas de HTML dans vos URL, cette tâche devient plus difficile. Lorsque vous développez des SPA, tout ce que vous avez sur votre page est JavaScript et JSON. Inertia a introduit une fonctionnalité de Server-Side Rendering (SSR) que vous pouvez ajouter à votre application. Cela permet à votre application de pré-rendre une page initiale visitée sur le serveur, puis d’envoyer le HTML rendu au navigateur. Cela permet aux utilisateurs de voir et d’interagir avec vos pages avant qu’elles ne soient entièrement chargées, et cela présente également d’autres avantages, comme la réduction du temps nécessaire aux moteurs de recherche pour indexer votre site.

Pour résumer son fonctionnement, Inertia identifiera s’il fonctionne sur un serveur Node.js et rendra les noms des composants, les propriétés, l’URL et la version des actifs en HTML. Cela fournira à l’utilisateur et au moteur de recherche pratiquement tout ce que votre page a à offrir.

Cependant, comme nous avons affaire à Laravel, cela n’a guère de sens car Laravel est un framework PHP et ne fonctionne pas sur un serveur Node.js. Par conséquent, nous transmettrons la demande à un service Node.js, qui rendra la page et renverra du HTML. Cela rendra notre application Laravel Vue SEO friendly par défaut.

Tout d’abord, nous devons installer le paquet Vue.js SSR npm :

npm install @vue/server-renderer

Un autre paquet « NPM » utile d’Inertia fournit un simple serveur « HTTP ». Il est fortement recommandé de l’installer :

npm install @inertiajs/server

Ensuite, dans « resources/js/ », nous allons ajouter un nouveau fichier nommé ssr.js. Ce fichier sera très similaire au fichier app.js que nous avons créé lors de l’installation d’Inertia, sauf qu’il s’exécutera dans Node.js plutôt que dans le navigateur :

import { createSSRApp, h } from "vue";
import { renderToString } from "@vue/server-renderer";
import { createInertiaApp } from "@inertiajs/inertia-vue3";
import createServer from "@inertiajs/server";
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";
import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m";

const appName = "Laravel";

createServer((page) =>
    createInertiaApp({
        page,
        render: renderToString,
        title: (title) => `${title} - ${appName}`,
        resolve: (name) =>
            resolvePageComponent(
                `./Pages/${name}.vue`,
                import.meta.glob("./Pages/**/*.vue")
            ),
        setup({ app, props, plugin }) {
            return createSSRApp({ render: () => h(app, props) })
                .use(plugin)
                .use(ZiggyVue, {
                    ...page.props.ziggy,
                    location: new URL(page.props.ziggy.location),
                });
        },
    })
);

Veillez à ne pas tout inclure dans le fichier ssr.js car il ne sera pas visible pour les visiteurs ; ce fichier est uniquement destiné aux moteurs de recherche et aux navigateurs pour afficher les données dans votre page, donc n’incluez que ce qui est important pour vos données ou seulement ce qui rendra vos données disponibles.

« Par défaut, le serveur SSR d’Inertia fonctionnera sur le port 13714. Cependant, vous pouvez changer cela en fournissant un second argument à la méthode createServer. » Inertia DOCss.

Les DOC d’Inertia.js n’expliquent pas comment intégrer le SSR d’Inertia à Vite, mais nous allons le faire maintenant. Allez dans vite.config.js et collez ce qui suit :

import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
    plugins: [
        laravel({
            input: "resources/js/app.js",
            ssr: "resources/js/ssr.js",
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
});

Ensuite, dirigez-vous vers package.json et modifiez le script de construction :

"build": "vite build && vite build --ssr"

Maintenant, si nous exécutons npm run build, Vite construira notre bundle SSR pour la production. Pour plus d’informations à ce sujet, vous pouvez visiter Inertia SSR DOCs et Vite SSR DOCs.

Titre et méta

Étant donné que les applications JavaScript sont rendues dans le document <body>, elles ne peuvent pas rendre les balises dans le document <head> car elles sont en dehors de leur champ d’application. Inertia possède un composant <Head> qui peut être utilisé pour définir la page <title>, les balises <meta> et d’autres composants <head>.

Pour ajouter l’élément <head> à votre page, nous devons importer <Head> d’Inertia comme nous l’avons fait avec le composant <Link>:

import { Head } from '@inertiajs/inertia-vue3'

<Head>
  <title>Kinsta Blog</title>
  <meta name="description" content="Kinsta blog for developers">
</Head>

Nous pouvons également ajouter un titre global pour toutes les pages, cela ajoutera le nom de votre application à côté du titre sur chaque page. Nous avons déjà fait cela dans le fichier app.js:

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    //
});

Ce qui signifie que si nous ajoutons <Head title="Home"> dans la page d’accueil de notre application avec un titre, cela sera rendu comme ceci : <title>Home - My App</title>.

Surveillance de votre application

La vitesse est l’un des facteurs les plus importants pour optimiser les performances de référencement de votre site web. Si vous utilisez WordPress pour votre site, pour cette raison, Kinsta APM vous aidera à surveiller et à garder un œil sur votre application en action. Il vous aide à identifier les problèmes de performance de WordPress et est disponible gratuitement sur tous les sites hébergés par Kinsta.

Résumé

Inertia.js est l’une des technologies les plus significatives disponibles ; mélangez-la avec Laravel et vous avez une application monopage moderne construite avec PHP et JavaScript. Taylor Otwell, le créateur de Laravel, s’intéresse tellement à Inertia que Laravel a lancé ses kits de démarrage les plus populaires, Laravel Breeze et Jetstream, avec le support d’Inertia et de SSR.

Si vous êtes un fan de Laravel ou un développeur professionnel, Inertia.js attirera sans aucun doute votre attention. Dans ce tutoriel, nous avons réalisé un blog très basique et simple en quelques minutes seulement. Il y a encore beaucoup à apprendre sur inertia, et ce n’est peut-être que le premier de nombreux articles et tutoriels.

Quels autres aspects de Laravel aimeriez-vous que nous explorions ? Faites-le nous savoir dans la section des commentaires ci-dessous.

Mostafa Said

I’m Mostafa, a full-stack developer with a knack for all things Laravel, Inertia, and JavaScript frameworks. When I'm not coding, you can find me sharing my knowledge through tutorials, diving into hackathons (and winning a few), and spreading the love for tech by teaching what I've learned.