Single-page applications (SPAs) have become the modern way of creating web applications, and Inertia.js is a leading tool allowing developers to create SPAs with both client-side and server-side rendering.

In this article, we’ll look at how Inertia makes constructing SPAs a piece of cake and how it solves many other problems for developers. We will also cover key features of the tool.

But before we begin, let’s first ensure that we understand how server-side and client-side applications work.

What Is Server-Side Rendering?

Server-side rendering (SSR) is when an application can render or display web page content on the server rather than in the browser. When a user attempts to visit example.com, the browser makes a request to the server asking for all necessary information to display this specific web page, and the server instantly responds by providing the browser with a fully rendered page.

Search engines intervene and index information supplied by the server before it reaches the browser; this is known as search engine optimization (SEO). The browser then resolves JavaScript content, and the web page gets displayed to the user.

A diagram showing the stages of server-side rendering.
Displaying content rendered on the server side.

The problem with the SSR approach is that it takes a long time to load a fully rendered page from the server, which does not offer a pleasant user experience. This is why developers consider SPAs and client-side rendering.

What Is Client-Side Rendering?

Client-side rendering allows the browser to have all it needs to render the web page from the client side instead of receiving a fully rendered page from the server. When the page is loaded, the browser does not send any other requests to the server, making the browsing experience extremely quick.

A diagram showing the stages of client-side rendering.
Displaying content rendered on the client side.

Client-side rendering helped in the creation of SPAs, revolutionizing the web. You can create a website that does not require reloading the page regardless of how many links you click. It makes it simple for the user to navigate through the website.

Although SPAs are fantastic, this approach has a lot of complexity and issues that we will cover today. Inertia addresses the majority of these issues by effectively utilizing server-side frameworks. It combines the best features of both server- and client-side apps.

What Is Inertia.js?

Inertia is not a JavaScript framework. Instead, it is a strategy or technique for developing SPAs. It allows the developer to utilize current server-side frameworks to build a modern SPA without the complexity that comes with it.

Inertia was designed to accompany, not replace, the frameworks you already use. Consider it a helpful ally that assists you in completing tasks more quickly and efficiently. It currently supports three frontend frameworks (Vue, React, and Svelte) for client-side rendering and two backend frameworks (Laravel and Rails) for server-side rendering.

For most Laravel developers, Inertia is one of the most reliable techniques for constructing SPAs since it allows them to connect both frontend and backend frameworks.

How Does Inertia.js Work?

Inertia is similar to Vue Router, in that it allows you to move between pages without having to reload the entire page. However, Inertia works in sync with your server-side framework. This is possible with Link, a wrapper for the standard anchor tag. When a Link is clicked, Inertia intercepts the click event and sends an XHR request to the server, causing the server to recognize that this is an Inertia request and return a JSON response. That response includes the JavaScript component name and data, after which Inertia magically removes unneeded components and replaces them with the ones required for visiting the new page and updates the history state.

A Deep Dive Into Inertia.js Functionality

When a visitor initially visits example.com, the browser performs a standard full-page request, and the server returns a complete HTML response as if Inertia did not exist. This HTML response has all of the site assets (CSS, JavaScript), but it also contains an extra asset for Inertia, which is the root div with the data-page attribute containing JSON data for the initial page. Inertia then uses this JSON data to kick-start the frontend framework and display the initial page.

Diagram showing actions on first visit to a web page when using Inertia.js.
Inertia.js: Initial page visit response.

Once the app is booted, each route the user visits inside the same domain using Link will be an XHR request with the X-Inertia header. This tells the server that this is an Inertia request.

The feedback will come as a JSON response with the page content, rather than a complete HTML response as with the initial visit.

Diagram showing actions when accessing other routes when using Inertia.js.
Inertia.js: Subsequent route visit response.

What Problems Does Inertia.js Solve?

Inertia addresses a large number of problems for web developers. The goal of creating Inertia was to give quick and effective solutions to all of the complexity that come with designing an SPA.

SPA Complexities

If developers were to build an SPA without Inertia, they would need to create REST or GraphQL APIs and protect them with some sort of authentication method, which would necessitate the creation of a front-end state-management system, among many other things.

Inertia was designed to help developers transform their server-side applications running completely on the backend server to a single-page JavaScript application without having to go through all of the complexities that come with building SPAs.

Creating an SPA using Inertia is similar to creating a server-side rendered app. You create controllers, make queries to the database for the required data, and then return the results to the views.

The key here is that the views are JavaScript components. This means you get the data from your server, then Inertia works with the frontend framework to show the page containing the data as a JavaScript file, eliminating the need to create APIs.

Authentication

Because Inertia feeds the application with data and responses from the backend, it will simply use whatever authentication system you have on the server-side. This means you won’t have to worry about client-side authentication — you’ll instead have a session-based authentication system that syncs with your server-side authentication system.

SEO Concerns

As explained previously for server-side rendering, search engines intercept the server response to the browser to index the web page’s HTML content. In the case of an SPA, search engines will have a hard time identifying the page’s content since the server will respond with either JavaScript components and JSON data.

But Inertia solved this concern by introducing the server-side rendering (SSR) feature that you can add to your application. Inertia uses the Node.js environment as a trigger to convert the JSON data response to HTML.

To better illustrate this, imagine Inertia sitting between the server and the browser, watching. When the server receives an Inertia request and returns a JSON response, Inertia detects the existence of a Node.js server, transforms the JSON response to HTML, and returns it, allowing search engines to index the page as if the app were not an SPA.

Inertia also provides a Head component, which allows you to add a title and meta data to your page:


<script setup>
import { Head } from '@inertiajs/inertia-vue3'
</script>

<template>
  <Head>
    <title>Page Title</title>
    <meta name="description" content="Page Description" />
  </Head>
</template>

Here is another example from Inertia’s online documentation:


// Layout.vue

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

<Head>
  <title>My app</title>
  <meta head-key="description" name="description" content="This is the default description" />
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
</Head>

// About.vue

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

<Head>
  <title>About - My app</title>
  <meta head-key="description" name="description" content="This is a page specific description" />
</Head>

Forms and Form Helper

It is possible to submit a standard form request while using Inertia. However, doing so will result in a full-page refresh.

Inertia allows users to make form requests using Inertia, which removes the possibility of page refreshing. Once the form is submitted with Inertia, it gets handled server-side, freeing you to redirect the user back to the same page (or a completely different page).

Inertia makes our lives easier when creating and submitting forms. Here’s an example on how you can use it with Vue.js 3 composition API:


<script setup>
  import { useForm } from "@inertiajs/inertia-vue3";

  const form = useForm({
    email: null,
    password: null,
  });
</script>

<template>
  <form @submit.prevent="form.post('kinsta/login')">
    <!-- email -->
    <input type="text" v-model="form.email" />
    <!-- password -->
    <input type="password" v-model="form.password" />
    <!-- submit -->
    <button type="submit">Login</button>
  </form>
</template>

You can submit the form with GET, POST, PUT, PATCH and DELETE.


<script setup>
  import { useForm } from "@inertiajs/inertia-vue3";

  const form = useForm({
    email: null,
    password: null,
  });

  const submit = () => {
    form.post("kinsta/login");
  };
</script>

<template>
  <form @submit.prevent="submit()">
    <!-- email -->
    <input type="text" v-model="form.email" />
    <!-- password -->
    <input type="password" v-model="form.password" />
    <!-- submit -->
    <button type="submit">Login</button>
  </form>
</template>

Inertia’s form helper is also offering a few helpful properties such as processing property which turns to true once the form starts processing. This can be used to disable submit buttons while the form is processing in order to prevent multiple submissions:


<button type="submit" :disabled="form.processing">Submit</button>

You can also use preserveState, preserveScroll and event callbacks with the form which will be helpful when adding additional options to the form:


form.post('kinsta/login, {
  preserveScroll: true,
  onSuccess: () => form.reset('password'),
})

Remembering State With Inertia.js

Let’s say a user is filling out a form on your website and decides to navigate away to another page before submitting it. When they return to the form page, the user’s form input will be reset.

Thankfully, Inertia provides the useRemember feature, which allows you to save the user’s form inputs to the history state and restore them on history navigation.

You can use this feature by importing it from Inertia and applying it to your form:


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

export default {
  setup() {
    const form = useRemember({
        first_name: null,
        last_name: null,
    })

    return { form }
  },
}

If you have a page with many forms that use the useRemember feature, each component must have a unique key so that Inertia knows which data to restore to each component:


const form = useRemember({
        first_name: null,
        last_name: null,
    }, 'Users/Create')

We don’t need to use the useRemember feature while utilizing Inertia’s form helper. Inertia will remember the state of the form input automatically, so we just need to give a unique identifier:


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

const form = useForm('CreateUser', data)

The nice aspect about this functionality is that you can remember any data in your application manually. This can also be useful for passing data from a deeply nested component to the main component:


import { Inertia } from '@inertiajs/inertia'

// DeeplyNestedComponent.vue
Inertia.remember(data, 'my-key')

// MainComponent.vue
let data = Inertia.restore('my-key')

File Uploads

Inertia detects if the form includes files and, if so, transforms the request data to the formData object, which is always required. So if you have a form that includes a name and an avatar, Inertia will treat the form as multipart/form-data.

Validation and Errors

When a user submits a form with incorrect values and it is sent to the server for validation, you return the user to the form page with a flash of validation errors in the session. Inertia captures errors from the session and saves them as page props.

Since props are reactive, they appear when the form submission is completed. In order for Inertia to detect the existence of errors, it keeps an eye on page.props.errors.

Once it’s found errors, it then provides an onError() callback instead of onSuccess().

Here is an example with Vue 3 to help you understand the concept:


const submit = () => {
    form.post("kinsta/login", {
        onError: () => {
            return "Hi! , the server returned an error and Inertia saved it as a prop. Do as you like with me"
        },
        onSuccess: () => {
            return "Wohoo!!"
        }
    }
    );
  };

Displaying errors is as easy as defining them as props and conditionally display them in your HTML:


<script setup>
  defineProps({
    errors: Object,
  });

//
</script>

<template>
  <form @submit.prevent="submit()">
    //
    <div v-if="errors.email">{{ errors.email }}</div>
  </form>
</template>

While using Inertia, you don’t need to worry about old input data in case of any errors. Once Inertia detects that the user has been redirected to the page with errors, it automatically preserves the component’s old state for POST, PUT, PATCH and DELETE.

Partial Reloads With Inertia.js

Inertia’s partial reload functionality is just excellent since it only reloads a selected component on the page rather than fetching the entire data set from the server again. This takes your application optimization to the next level. You can also visit the following link to Learn more about how to optimize your Laravel application’s performance.

Partial reloads can be performed by using Inertia’s only property:


import { Inertia } from '@inertiajs/inertia'

Inertia.visit(url, {
  only: ['users'],
})

External Redirects With Inertia.js

Subdomain routing, or external redirection, is one of the most frustrating challenges with SPAs. It is irrational to expect your application to remain a single-page application while also visiting a different domain.

It may be necessary to redirect an Inertia request to an external website or even another non-Inertia endpoint in your app. This is possible through a server-side-initiated window.location visit:


return Inertia::location($url);

If you open the console during testing this out, you will find that it returns 409 conflict. This response contains the URL in the X-Inertia-Location header, which Inertia will detect on the client side and automatically perform the visit.

How To Work With Inertia.js

Working with Inertia is similar to working on a server-side application, with the exception that it is a fully reactive single-page application. You should be able to define your routes, customize controllers, and return a view for Inertia to send to your frontend framework.

Laravel Routes and Inertia.js

Laravel routing is not something you want to give up when developing your application; it allows you to quickly construct the most complex routes, and there are plenty of free and paid Laravel resources out there that can help you learn more about Laravel and how routing works.

The beauty here is that you don’t need Vue Router or React Router to conduct simple client-side routing because Inertia has its own routing system that works with Laravel routing. If the job does not require any backend data, you may use the router helper to route directly to a component.


Route::inertia('/home', 'HomeComponent');

public function index()
    {
    return Inertia::render('Users/Index', [
        'users' => User::all();
        'create_url' => URL::route('users.create'),
    ]);
}

Before we move on, we’d like to introduce you to DevKinsta, a powerful tool for developers, designers, and agencies that enables them to construct single- and multi-page WordPress web apps. Fortunately, WordPress can be integrated with Laravel using the Corcel package. If you build a Laravel app with WordPress integration, check out Kinsta APM Tool for extraordinary performance monitoring.

Redirects

You should always redirect the user to the correct path that corresponds to the initial request. For example, if a user is submitting to store endpoint to submit a post, make sure to redirect the customer to GET endpoint maybe to the post route.


public function store()
{
    Post::create(
        Request::validate([
            'title' => ['required'],
            'body' => ['required'],
        ])
    );

    // redirect the user to the posts show page
    return Redirect::route('posts.show');
}

Disadvantages of Using Inertia.js

So far, we’ve focused on the several advantages of using Inertia. However, as with any tool, Inertia also has drawbacks.

  • The user must have basic knowledge of Vue or React.
  • Since model data can be passed completely to the client side, the user must make sure to explicitly return the relevant data to the frontend.
  • APIs must be recreated if the web application is to have an Android or iOS application at any time.

Should You Use Inertia.js?

To answer the question of whether or not you should use Inertia, the answer is yes, if you want to build a single-page, server-side, SEO-driven modern app.

You can learn more by visiting the official Inertia.js website and reading the documentation.

Summary

Client-side apps and SPAs are growing increasingly popular as web technologies evolve, whereas server-side traditional applications have begun to fall by the wayside. More than ever before, it’s important to have the right tools at hand.

Inertia is a fantastic modern approach or solution for server-side developers to build single-page apps. It solves so many problems and saves so much time.

As we discussed in our article, Inertia now supports server-side rendering, which takes it to a whole new level by allowing developers to create SEO-driven SPAs.

Inertia is also receiving a lot of love from the community. The development effort is sponsored by Laravel Forge, Laracasts, and a number of other fine organizations. As a result, Inertia is a reliable tool that will be improved and maintained into the future for Laravel developers, particularly as the demand for Laravel coders continues to grow.

And if you’re looking for your Intertia-powered project’s next home, check out Kinsta’s Application Hosting offerings.