Inertia no es un framework ni los remplaza, ya sea del lado del servidor o del cliente, simplemente trabaja junto a ellos conectándolos para hacer más fácil el desarrollo de Single-Page Apps completamente renderizadas. Esto lo hace mediante adaptadores, que actualmente cuenta con tres para el lado del cliente (React, VueJS y Svelte) y para el lado del servidor cuenta con dos (Laravel y Rails).

En esta ocasión haremos un pequeño tutorial para implementar Inertia JS usando Laravel y VueJS.

Para comenzar tenemos un proyecto de Laravel 8 creado y su entorno de desarrollo generado mediante Lando (Si te interesa saber cómo usar Lando entra aquí).

Comenzaremos haciendo la instalación de Inertia JS del lado del servidor vía composer con el comando:

composer require inertiajs/inertia-laravel

Ahora se debe definir el template base en la vista principal de nuestra aplicación. Sólo debemos agregar la etiqueta "@inertia" en donde queremos que se rendericen los componentes de VueJS y cargamos los assets del sitio (CSS y JS):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
    <link href="{{ mix('/css/app.css') }}" rel="stylesheet"></link>
    <script src="{{ mix('/js/app.js') }}" defer></script>
    <title>Inertia JS</title>
</head>
<body>
@inertia
</body>
</html>
app.blade.php

Lo siguiente es agregar el middleware de Inertia usando el comando:

php artisan inertia:middleware

Después registramos el HandleInertiaRequests middleware en nuestro archivo App\Http\Kernel.

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

Esa es toda la configuración del lado del servidor que necesitamos, ahora configuremos el lado del cliente.

Primero hay que instalar NPM:

npm install

Asegúrate de tener una versión de node reciente para poder usar VueJS 3, y actualiza los scripts en el archivo package,json con el siguiente código:

"scripts": {
    "development": "mix",
    "watch": "mix watch",
    "watch-poll": "mix watch -- --watch-options-poll=1000",
    "hot": "mix watch --hot",
    "production": "mix --production"
},
package.json

y ahora instalaremos los paquetes de Inertia para VueJS 3:

npm install @inertiajs/inertia @inertiajs/inertia-vue @inertiajs/inertia-vue3  @inertiajs/progress laravel-mix@next vue@next

Probablemente te pida instalar más dependencias necesarias, después de instalar todo, el archivo package.json debería verse así:

{
    "private": true,
    "scripts": {
        "development": "mix",
        "watch": "mix watch",
        "watch-poll": "mix watch -- --watch-options-poll=1000",
        "hot": "mix watch --hot",
        "production": "mix --production"
    },
    "devDependencies": {
        "@vue/compiler-sfc": "^3.0.2",
        "axios": "^0.19",
        "cross-env": "^7.0",
        "laravel-mix": "^6.0.0-beta.14",
        "lodash": "^4.17.19",
        "postcss": "^8.1.6",
        "resolve-url-loader": "^3.1.0",
        "vue-loader": "^16.0.0-rc.1",
        "vue-template-compiler": "^2.6.12"
    },
    "dependencies": {
        "@inertiajs/inertia": "^0.6.1",
        "@inertiajs/inertia-vue": "^0.4.1",
        "@inertiajs/inertia-vue3": "^0.2.1",
        "vue": "^3.0.2"
    }
}
package,json

y el archivo webpack.mix.js así:

mix.js('resources/js/app.js', 'public/js')
    .postCss('resources/css/app.css', 'public/css', [
        //
    ]).vue();
webpack.mix.js

Para que Inertia pueda resolver el componente que se va a renderizar debemos agregar el siguiente código en el archivo resources\js\app.js o tu archivo principal de Javascript.

import { createApp, h } from 'vue'
import { App, plugin } from '@inertiajs/inertia-vue3'

const el = document.getElementById('app')

createApp({
    render: () => h(App, {
        initialPage: JSON.parse(el.dataset.page),
        resolveComponent: name => require(`./Pages/${name}`).default,
    })
}).use(plugin).mount(el)
app.js

Esto sólo está iniciando el componente base y resolverá el componente solicitado por medio de su nombre, este debe estar dentro del directorio resources\Pages.

Lo siguiente es crear el componente llamado Index en el directorio resources\Pages\Home con el código:

<template>
    <div>
        <h1>Hello World</h1>
    </div>
</template>
Index.vue

Ahora crearemos el controlador que usará el componente para renderizar la vista, lo llamaremos HomeController que tendrá la función Index:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Inertia\Inertia;

class HomeController extends Controller
{
    public function index()
    {
        return Inertia::render('Home/Index');
    }
}
HomeController.php

Por último, agregaremos la ruta para poder acceder a la función creada:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;

Route::get('/', [HomeController::class, 'index'])->name('home');
web.php

Ahora sólo debemos compilar los archivos de CSS y JS con el siguiente comando:

npm run development

Si ya tienes corriendo tu servidor local ya se debería mostrar el componente creado en la URL base del sitio.

Con esto comprobamos que la configuración realizada ha sido correcta, ahora podemos proceder explorando algunas de las características de Inertia JS.

Para agregar información al componente simplemente se debe mandar mediante la función para renderizar el componente:

public function index()
{
    return Inertia::render('Home/Index', [
    	'data' => 'Datos enviados',
    ]);
}
HomeController.php

Ahora agregamos la información al componente:

<template>
    <div>
        <h1>Hello World</h1>
        <p>{{ data }}</p>
    </div>
</template>

<script>
export default {
    props: {
        data: String,
    },
}
</script>
Index.vue

Y en el navegador se debería mostrar lo siguiente:

En el siguiente ejemplo vemos uno de los beneficios de Ineria JS que usa las rutas de Laravel sin tener que hacer cambios.

Primero agregamos la función para la otra ruta:

public function index()
{
    return Inertia::render('Home/Index', [
        'data' => 'Datos enviados',
        'link' => route('link'),
    ]);
}

public function link()
{
    return Inertia::render('Home/Link', [
        'data' => 'Otros datos enviados',
        'link' => route('home'),
    ]);
}
HomeController.php

Agregamos la ruta nueva:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;

Route::get('/', [HomeController::class, 'index'])->name('home');
Route::post('/link', [HomeController::class, 'link'])->name('link');
web.php

Y por último agregamos el enlace en el componente Index y creamos el componente Link:

<template>
    <div>
        <h1>Hello World</h1>
        <p>{{ data }}</p>
        <inertia-link :href="link" method="post">Link</inertia-link>
    </div>
</template>

<script>
export default {
    name: "Home",
    props: {
        data: String,
        link: String,
    },
}
</script>
Index.vue
<template>
    <div>
        <h1>Link</h1>
        <p>{{ data }}</p>
        <inertia-link :href="link">Home</inertia-link>
    </div>
</template>

<script>
export default {
    name: "Link",
    props: {
        data: String,
        link: String,
    },
}
</script>

<style scoped>

</style>
Link.vue

Y en el navegador podemos comprobar el re direccionamiento:

El paquete Inertia JS nos ayuda a crear rápidamente SPAs ya que nos permite usar el enrutamiento, middlewares, autenticación y otras características de Laravel como si las hiciéramos desde un Framework para el lado del cliente sin tener la complejidad de crear una API.

Si quieres encontrar más información sobre Inertia JS haz clic aquí.

En posts siguientes profundizaremos en cómo usar Inertia JS para crear formularios, subir archivos y otras características más avanzadas.