How to use Inertia.js in Laravel project?

Multi-page applications (MPAs) are becoming less and less popular. Well-known platforms like Facebook, Twitter, YouTube, Github and many others are already using Single Page Application (SPA) technology instead.

This trendy technology allows users to engage with web applications quickly and responsively because everything is rendered client-side. However, this can be a pain for developers building server-side rendered applications using frameworks like Laravel or Django.

Luckily, Inertia.js stepped in and came to our rescue.

In this article, we will show how to use Inertia.js with Laravel, Vue.js, and Tailwind CSS to create a modern blogging web application. We’ll also share how to make your SPA more SEO-friendly, along with some other tips.

If you're just getting started with Laravel, we recommend reading this article first so you're ready.

Why SPA?

Before we ask why Inertia, we must first ask: "Why SPA?"

Why would anyone prefer client-side rendered applications to traditional server-side applications? What forces a full-stack Laravel developer to say goodbye to blade components ?

Short answer: Because speed and responsiveness are keys to any successful user engagement.

In the case of MPA, the browser keeps sending requests to the backend and then performs a large number of database queries. After the database and server process the query and pass it to the browser, the page is rendered.

But SPA is different. The application brings everything the user needs directly to the page, eliminating the need for the browser to send queries or reload the page to render new HTML elements.

Because of this unique user experience, many big-name companies are clamoring to turn their websites into single-page applications.

That said, creating a single page application is difficult for Laravel developers because it requires them to start using Vue.js or React instead of blade templates, resulting in the loss of many Laravel gems to save time and effort.

However, now that we have Inertia.js, this all changes.

Why choose Inertia?

If Laravel developers were to build Web SPAs with Vue before Inertia, they would have to use Laravel to set up the API and return JSON data, and then use something like AXIOS to retrieve the data in the Vue component. They would also need something like Vue Router to manage it routing, which would mean losing Laravel's routing, as well as middleware and controllers.

Inertia.js, on the other hand, enables developers to build modern single-page Vue, React and Svelte applications using classic server-side routing and controllers. Inertia is designed for Laravel, Ruby on Rails, and Django developers, allowing them to build applications without changing their coding techniques for creating controllers, getting data from databases, and rendering views.

Laravel developers will feel right at home thanks to Inertia.js.

How Inertia works

Building a SPA with just Laravel and Vue will give you a full JavaScript page on the front end, but it won't give you a single-page application experience. Every link clicked will cause your client-side framework to restart on the next page load.

This is where Inertia comes into the picture.

Inertia is basically a client side routing library. It allows you to navigate between pages without reloading the entire page. This is  <Link> achieved through components, which are lightweight wrappers around standard anchor tags.

When you click on an Inertia link, Inertia intercepts the click and redirects you to XHR. The browser does not reload the page this way, giving the user a complete single-page experience.

Get started with Inertia

A sample page made with Inertia.js

A sample page made with Inertia.js

To understand Inertia and how to integrate it with Laravel, we will build a blogging web app using the most powerful combination of Laravel for the backend, Vue.js for the JavaScript frontend, and Tailwind CSS for styling.

If you'd rather follow this tutorial in a local environment, you can use DevKinsta , a powerful tool for developers, designers, and agencies that enables them to build single-page and multi-page WordPress web applications. Fortunately, WordPress can be easily integrated with Laravel using the Corcel package.

Prerequisites

To get the most from this tutorial, you should be familiar with the following:

  • Laravel basics (installation, databases, database migrations, Eloquent models, controllers, and routing)
  • Vue.js basics (installation, structure, and forms)

If you're feeling unsure, check out these great free and paid tutorials on Laravel . Otherwise, let's get started.

Step 1: Install Core Elements

In order to focus on Inertia.js and get straight to the fun part, make sure you have the following settings ready:

  1. The newly installed Laravel 9 project is named blog
  2. Installed Tailwind CSS CLI in our Laravel project
  3. The two blade components in blog/resources/views are used to view the blog's homepage and an article on the blog, as shown in the following figure: "
    /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>博客 - 闪电博</title>
    
    </head>
    
    <body>
    
    <header>
    
    <h1>博客 - 闪电博</h1>
    
    </header>
    
    <main>
    
    <h2>Read our latest articles</h2>
    
    <section>
    
    <article>
    
    <div>
    
    <img src="/images/wbolt-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>博客 - 闪电博</title>
    
    </head>
    
    <body>
    
    <main>
    
    <article>
    
    <div>
    
    <img src="/images/wbolt-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>

  4. blogConnect to our project a MySQL local database named: " .env " :
    DB_CONNECTION=mysql
    
    DB_HOST=127.0.0.1
    
    DB_PORT=3306
    
    DB_DATABASE=blog
    
    DB_USERNAME=root
    
    DB_PASSWORD=

  5. Article models, migrations and factories: "app/Models/ Article.php ".
    <?php
    
    namespace AppModels;
    
    use IlluminateDatabaseEloquentFactoriesHasFactory;
    
    use IlluminateDatabaseEloquentModel;
    
    class Article extends Model
    
    {
    
    use HasFactory;
    
    protected $fillable = ['title', 'excerpt', 'body'];
    
    }
    
    “database/migrations/create_articles_table.php“:
    
    <?php
    
    use IlluminateDatabaseMigrationsMigration;
    
    use IlluminateDatabaseSchemaBlueprint;
    
    use IlluminateSupportFacadesSchema;
    
    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 IlluminateDatabaseEloquentFactoriesFactory;
    
    class ArticleFactory extends Factory
    
    {
    
    public function definition()
    
    {
    
    return [
    
    'title' => $this->faker->sentence(6),
    
    'excerpt' => $this->faker->paragraph(4),
    
    'body' => $this->faker->paragraph(15),
    
    ];
    
    }
    
    }

That’s all we need to get started! Now let’s get down to business and introduce Inertia.js into our project.

Step 2: Install Inertia

The installation process of Inertia is divided into two main stages: server side (Laravel) and client side (VueJs).

The official installation guide in the Inertia documentation is a bit out of date, as Laravel 9 now defaults to Vite , but we'll take a look at that too.

1. Server-Side

The first thing we need to do is install the Inertia server-side adapter via Composer using the following terminal command.

composer require inertiajs/inertia-laravel

Now we will set up our root template, which will be a single blade file that will be used to load your CSS and JS files, and an Inertia root that will be used to launch our JavaScript application.

Since we are using the latest version of Laravel 9 v9.3.1, we also have to let Vite work its magic by including this in the /resources/views/ app.blade.php tag:

<!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>

Notice how we   dynamically get the item title by <title> adding an attribute to the tag  .Inertia

We also added  @vite directives in the header to let Vite know the path to the main JavaScript file where we create the app and import the CSS. Vite is a tool that aids JavaScript and CSS development, allowing developers to view front-end changes during local development without having to refresh the page.

Our next step will be to create the HandleInertiaRequests middleware and publish it to our project. We can do this by issuing the following terminal command from the root directory of our project.

php artisan inertia:middleware

Once done, go to "App/Http/ Kernel  " and register  HandleInertiaRequests as the last item your web middleware:

'web' => [

// ...

AppHttpMiddlewareHandleInertiaRequests::class,

],

2. Client-Side

Next, we have to install our front-end Vue.js 3 dependencies in the same way as the server side:

npm install @inertiajs/inertia @inertiajs/inertia-vue3

// or

yarn add @inertiajs/inertia @inertiajs/inertia-vue3

Next, you need to pull in Vue.js 3:

npm install vue@next

Then update your main JavaScript file to initialize Inertia.js with Vue.js 3, Vite and 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);

},

});

In the above code snippet, we use Laravel's plugin  resolvePageComponentand tell it to resolve our component from the directory ./Pages/$name.vue . This is because we will save our Inertia components in this directory in future projects, and this plugin will assist us in automatically loading these components from the correct directory.

All that's left is installation  vitejs/plugin-vue:

npm i @vitejs/plugin-vue

And update  the 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,

},

},

}),

],

});

The final step is to install our dependencies and compile our files.

npm install

npm run dev

And that's it! You've got a Laravel 9 application using Vue.js 3 and Vite. Now, we need to see something actually happen!

Create Inertia page

Do you remember the two blade files ( index and show ) used to view our home page and an article ?

When using Inertia, the only blade file we need is  app.blade.php , which we have already used once when installing Inertia. So, what happens to these files now?

We will convert these files from blade components to Inertia.js components.

Each page in your application has its own controller and Inertia JavaScript component. This lets you get only the data you need for that page without having to use the API. Inertia pages are nothing but JavaScript components, in our case they are Vue.js components. There is nothing particularly noteworthy about them. So what we're going to do is  <template> wrap all of our HTML content between tags, and anything that has to do with JavaScript will be  <script> wrapped in tags.

Create a folder called "Pages" and move your files there. Therefore, we will put " index.blade.php " and " show.blade.php " in " ./resources/js/Pages ". We will then change the file format to ".vue" instead of ".blade.php", capitalize the first letter of their names, and turn their contents into a standard Vue.js component. We will exclude  <html><head> and  <body> tags since they are already included in the main root blade component.

“resources/js/Pages/Index.vue“:

<script setup>

//

</script>

<template>

<header>

<h1>博客 - 闪电博</h1>

</header>

<main>

<h2>Read our latest articles</h2>

<section>

<article>

<div>

<img src="/images/wbolt-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>欢迎来到闪电博的博客频道</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>

One thing really bothers me! We've been copying and pasting our headers and footers in every component, which is not good practice. We are constantly copying and pasting our headers and footers in every component, which is not a very good practice. Let's create a basic Inertia layout to store our persistent components.

Create a folder named "Layouts" in " /resources/js " and create a file named "WboltLayout.vue" in the folder. This file will have our header and footer, as well as with  <slot /> ,  main to allow all the components wrapped with this layout to be embedded in it. The file should look like this:

“resources/js/Layouts/WboltLayout.vue“:

<script setup></script>

<template>

<header>

<h1>博客 - 闪电博</h1>

</header>

<main>

<slot />

</main>

<footer>

<h2>Join our Newsletter</h2>

<input type="email" />

</footer>

</template>

We will then import this new layout into our page and wrap all the HTML content within it. Our component should look like this:

Index.view :

<script setup>

import WboltLayout from "../Layouts/WboltLayout.vue";

</script>

<template>

<WboltLayout>

<section>

<h2>Read our latest articles</h2>

<article>

<div>

<img src="/images/wbolt-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>

</WboltLayout>

</template>

Show.vue :

<script setup>

import WboltLayout from "../Layouts/WboltLayout.vue";

</script>

<template>

<WboltLayout>

<article>

<h1>Title for the blog</h1>

<p>Article content goes here</p>

</article>

</WboltLayout>

</template>

Laravel routing and inertial rendering

First, let's seed some articles into our database using the " ArticleFactory " file from our tutorial starting point .

“database/seeders/databaseSeeder.php“:

<?php

namespace DatabaseSeeders;

use AppModelsArticle;

use IlluminateDatabaseSeeder;

class DatabaseSeeder extends Seeder

{

public function run()

{

Article::factory(10)->create();

}

}

Then click the following terminal command to migrate your tables and seed the fake data from the factory:

php artisan migrate:fresh --seed

This will create 10 fake articles in the database, which we will need to use Laravel routing to pass to our view. Now that we're using Inertia to render views, the way we used to write routes will change slightly. Let's create our first Laravel Inertia route in "routes/ web.php " and return the home page view from "/resources/js/Pages/Index.vue ".

“routes/web.php“:

<?php

use AppModelsArticle;

use IlluminateSupportFacadesRoute;

use InertiaInertia;

Route::get('/', function () {

return Inertia::render('Index', [

'articles' => Article::latest()->get()

]);

})->name('home');

Note that we imported Inertia and did not use Laravel's view() helper to return the view  Inertia::render. Inertia will also look for the file name we mentioned in "resources/js" in the Pages folder by default.

Go to the index file and set the retrieved data as props to  v-for loop over them to display the results. Between script tags, define the passed data as a prop. All Inertia needs to know is the data type you are expecting, in our case an "Article" object containing an array of articles.

“resources/js/Pages/Index.vue“:

<script setup>

import WboltLayout from "../Layouts/WboltLayout.vue";

defineProps({

Articles: Object,

});

</script>

Note that just defining it as a prop without returning it is enough, since we are using  setup the format of the Vue.js 3 composition API. If we are using the options API, then we need to return it.

Let's do this loop:

<template>

<WboltLayout>

<h2>Read our latest articles</h2>

<section>

// Looping over articles

<article v-for="article in articles":key="article.id">

<div>

<img src="/images/wbolt-logo.png" alt="Article thumbnail" />

</div>

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

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

<a href="#">Read more</a>

</article>

</section>

</WboltLayout>

</template>

npm run dev (Let it run since we are using Vite) and  php artisan serve to start the laravel development server, visit our website and we will see the expected page showing all ten articles in the database.

Right now, we are using the Vue DevTools extension for Google Chrome , which allows us to debug my application. Let's take a look at how our data is passed to the component.

Check the properties of Inertia

Check the properties of Inertia

"Articles" is passed to the component as a props object, containing an array of articles; each article in the array is also an object with properties corresponding to the data it got from the database. This means any data we transfer from Laravel to Inertia will be treated as a prop.

Tailwind CSS integration with Inertia.js

Since Tailwind is already installed in our project at the beginning, all we need to do is tell it to read our Inertia component. This can be achieved by editing " tailwind.config.js " as follows:

/** @type {import('tailwindcss').Config} */

module.exports = {

content: [

"./storage/framework/views/*.php",

"./resources/views/**/*.blade.php",

"./resources/js/**/*.vue",

],

theme: {

extend: {},

},

plugins: [],

};

Then make sure we have imported our CSS file in "resources/js/ app.js ":

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

Now we are ready to style our component.

“resources/js/Pages/Index.vue“:

<script setup>

import WboltLayout from "../Layouts/WboltLayout.vue";

defineProps({

articles: Object,

});

</script>

<template>

<WboltLayout>

<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/wbolt-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>

</WboltLayout>

</template>

“resources/js/Layouts/WboltLayout.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">博客 - 闪电博</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>

If you take a look at the browser, you'll see that Vite has updated the page with Tailwind magic.

Rendered Inertia properties

Rendered Inertia properties

Now that we have a working homepage that displays all articles in the database, we need to create another route to display individual articles. Let's create a new route and set the URL to the "id" wildcard:

“routes/web.php

<?php

use AppModelsArticle;

use IlluminateSupportFacadesRoute;

use InertiaInertia;

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');

We imported the "Article" model and added a new route to return the Inertia component Show.vue . We also took advantage of Laravel's routing model binding , which allows Laravel to automatically fetch the article we are referring to.

What we need now is a way to access this route by clicking a link on the homepage without reloading the entire page. This is possible with Inertia's amazing tools  <Link> . We mentioned in the introduction that Inertia uses   wrappers <Link> as standard anchor tags  that are designed to make page access as seamless as possible. <a>In Inertia, <Link>a tag can act as  <GET> an anchor tag for executing requests, but it can also act as  <button> both  <form> . Let's see how we can apply this to our project.

In our Index.vue, we will import from Inertia  <Link>, remove the anchor tag  <a> and replace it with Inertia's  <Link> tag. href The property will be set to the route URL we created earlier for viewing the article:

<script setup>

import WboltLayout from "../Layouts/WboltLayout.vue";

import { Link } from "@inertiajs/inertia-vue3";

defineProps({

articles: Object,

});

</script>

<template>

<WboltLayout>

<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/wbolt-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>

</WboltLayout>

</template>

Let's use Tailwind to style Show.vue so it looks cleaner and ready for us to access. We also need to let it know that it should expect an "Article" object and set it as a prop:

<script setup>

import WboltLayout from "../Layouts/WboltLayout.vue";

defineProps({

article: Object,

});

</script>

<template>

<WboltLayout>

<article class="mx-auto mt-10 flex justify-center max-w-5xl border-b-2">

<img

src="/images/wbolt-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>

</WboltLayout>

</template>

Now when we click on the article title or "Read more" we will be magically transported to Show.vue without having to refresh the page.

Inertia link example

Inertia link example

In our example we use  <Link> as anchor tag, send  GET a request to the route and return new data, but we could also  <Link> use  POSTPUTPATCH and DELETE

“routes/web.php“:

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

Laravel integration Inertia tips and tricks

We now have a working SPA built with Laravel, Inertia and Tailwind CSS. But inertia can help us achieve more. Now it’s time to master some inertia techniques that will help both developers and app visitors.

Generate URLs

You may have noticed that we've been adding names to our Laravel routes without using them. Inertia allows us to use our named routes within components instead of writing out complete routes manually.

We can achieve this by installing the Ziggy package in our project :

composer require tightenco/ziggy

Then go to "resources/js/app.js" and update it like this:

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);

},

});

Go to "/resources/views/app.blade.php " and   update the header with the command :@route

<!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>

…and refresh your NPM package by clicking the following two terminal commands:

npm install && npm run dev

This package allows us to use named routes in our Inertia components, so let's head to Index.vue and delete the old manual route, replacing it with the route name while passing the data normally as we would in the controller.

We will replace the following:

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

{
   
   { article.title }}

</Link>

...for this:

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

{
   
   { article.title }}

</Link>

This will give us the exact same behavior, but it's more developer friendly, and it's very helpful when your route expects many parameters.

progress bar indicator

This is one of the best features of Inertia.js; since SPA provides an interactive user experience, having constant feedback on whether a request is loading would be a great addition to the application. This can be achieved through a separate library provided by Inertia.

The @inertiajs/progress library is a wrapper around NProgress that can conditionally display loading metrics based on inertia events. You don't really need to know how it works behind the scenes, so we just need to make it work.

We can install this library using the following terminal command:

npm install @inertiajs/progress

Once it is installed, we need to import it in " 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 });

This will show a black loading bar and a loading knob, but we can change the color as well as other useful options, which can be found in the Inertia.js progress indicator documentation .

Inertia progress indicator (top right)

Inertia progress indicator (top right)

scroll management

In some cases, you may want to navigate to a new page while maintaining the scroll position. Maybe you need to do this if you allow users to leave comments; this will submit a form and load new comments from the database into your component; you want this to happen without the user losing their scroll position. Inertia solves this problem for us.

In our case, let's apply it to the tag in  Index.vue<Link>  . <Link> In order to preserve the scroll position when redirecting to a different page  using Inertia  , all we need to do is <Link> add  preserve-scroll an attribute in .

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

{
   
   { article.title }}

</Link>

SEO tips

Since the birth of SPA, people have been paying attention to search engine optimization (SEO) issues. It is generally known that if you use the SPA approach, search engines will have a hard time crawling your web application because everything is client-side rendered, resulting in your website not showing up at the top of the search results; nevertheless, why Which popular platforms like Facebook and Github are now SPA and still perform well in terms of SEO?

Well, this is no longer a task: impossible. Inertia is providing some solutions to help your SPA become search engine friendly.

Inertia Vue SSR for Laravel and Vite

Search engines are always looking for HTML on your website in order to identify the content; however, if there is no HTML in your URL, the job becomes more difficult. When developing a SPA, you only have JavaScript and JSON on your pages. Inertia introduces a server-side rendering (SSR) feature that you can add to your application. This allows your application to pre-render an initial page visit on the server and then send the rendered HTML to the browser. This allows users to see and interact with your page before it's fully loaded, and it has other benefits, like shortening the time it takes for search engines to index your site.

To summarize how it works, Inertia will recognize if it is running on a Node.js server and render the component name, properties, URL and asset version into HTML. This will provide users and search engines with almost everything your page has to offer.

However, since we are dealing with Laravel, this doesn't make much sense, since Laravel is a PHP framework and does not run on a Node.js server. Therefore, we will forward the request to a Node.js service, which will render the page and return the HTML. This will make our Laravel Vue application SEO friendly by default.

First, we need to install the Vue.js SSR npm package:

npm install @vue/server-renderer

Another useful Inertia "NPM" package provides a simple "HTTP" server. We strongly recommend you install it:

npm install @inertiajs/server

Then, in "resources/js/" we will add a new file called ssr.js. This file will be very similar to the app.js file we created when installing Inertia , except it will be executed in Node.js instead of the browser:

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),

});

},

})

);

Make sure not to include everything in the ssr.js file as it won't be seen by your visitors; this file is just for search engines and browsers to display data in your page, so only include what's important for your data , or only include content that makes your data available.

"By default, Inertia's SSR server will run on port 13714. However, you can change this by providing a second argument to the createServer method." Inertia DOCss.

The Inertia.js DOCs don't explain how to integrate Inertia SSR with Vite, but we'll get to that now. Go to vite.config.js and paste the following:

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,

},

},

}),

],

});

Next, go to package.json and modify the build script:

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

Now, if we run  npm run build, Vite will build our SSR package for production. For more related information, you can visit  the Inertia SSR documentation  and  Vite SSR documentation .

Title and Meta

Because JavaScript applications are  <body> rendered within the document, they cannot  <head> render markup to the document because it is outside their scope. Inertia has a  <Head> component that can be used to configure the page  <title><meta> labels and other  <head> components.

<head> To add elements  to your page  , we have to import from Inertia <head>, just like we  <Link> did with components:

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

<Head>

<title>博客 - 闪电博</title>

<meta name="description" content="WordPress爱好者博客">

</Head>

We can also add a global title to all pages, which will add your application name next to the title of each page. We've done this in the app.js file:

createInertiaApp({

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

//

});

This means that if we add a title to the home page of our application  <head title="Homepage">, this will be rendered like this:  <title>Home - My App</title>.

Monitor your application

Speed ​​is one of the most important factors in optimizing your website’s SEO performance. If your website uses WordPress, for this reason, Kinsta APM will assist you in monitoring and keeping an eye on the operation of your application. It can help you identify WordPress performance issues.

summary

Inertia.js is one of the most important technologies out there; mix it with Laravel and you have a modern single-page application built with PHP and JavaScript. Taylor Otwell, the creator of Laravel, is very interested in Inertia , so much so that Laravel launched its most popular starter kits, Laravel Breeze and Jetstream, with support for Inertia and SSR.

If you are a fan of Laravel or a professional developer, Inertia.js will undoubtedly attract your attention. In this tutorial, we made a very basic and straightforward blog in just a few minutes. There is still a lot to learn about Inertia and this may just be the first of many articles and tutorials.

Guess you like

Origin blog.csdn.net/weixin_44026962/article/details/135463298