Como usar o Inertia.js em seus projetos Laravel

Publicados: 2022-12-08

Aplicativos de várias páginas (MPAs) estão ficando menos populares a cada dia. Plataformas famosas como Facebook, Twitter, YouTube, Github e muitas outras já estão usando a tecnologia de aplicativo de página única (SPA).

Essa tecnologia moderna permite que os usuários se envolvam com aplicativos da Web de maneira rápida e responsiva, porque tudo é renderizado no lado do cliente. No entanto, pode ser uma dor para os desenvolvedores que criam aplicativos renderizados do lado do servidor com estruturas como Laravel ou Django.

Felizmente, Inertia.js interveio e veio em socorro.
O ingrediente que faltava para seus projetos Laravel? Inertia.js. Saiba mais neste guia completo Click to Tweet
Neste artigo, mostraremos como você pode começar a usar o Inertia.js e como usá-lo com Laravel, Vue.js e Tailwind CSS para criar um aplicativo da web de blog moderno. Também compartilharemos como tornar os SPAs mais amigáveis ​​ao SEO, bem como alguns outros truques.

Se você está apenas começando com o Laravel, recomendamos que você leia este artigo primeiro para estar pronto para começar.

Por que SPA?

Antes de podermos perguntar por que devemos usar o Inertia, devemos primeiro perguntar: “Por que SPA?”

Por que alguém preferiria aplicativos renderizados do lado do cliente em vez de aplicativos tradicionais do lado do servidor? O que forçaria um desenvolvedor Laravel full-stack a dizer adeus aos componentes blade?

A resposta curta: porque velocidade e capacidade de resposta são essenciais para qualquer interação bem-sucedida do usuário.

No caso dos MPAs, o navegador constantemente envia solicitações ao back-end, que executa várias consultas ao banco de dados. Depois que o banco de dados e o servidor processam as consultas e as entregam ao navegador, a página é renderizada.

Mas SPAs são diferentes. O aplicativo traz tudo o que o usuário precisa direto para a página, eliminando a necessidade do navegador enviar consultas ou recarregar a página para renderizar novos elementos HTML.

Devido a essa experiência de usuário única, muitas empresas de renome estão clamando para que seus sites se tornem aplicativos de página única.

Dito isto, criar um aplicativo de página única pode ser difícil para os desenvolvedores do Laravel porque exigiria que eles começassem a usar Vue.js ou React em vez de modelos de lâmina, resultando na perda de muitas gemas do Laravel que economizam tempo e esforço.

Agora que temos o Inertia.js, tudo mudou.

Por que Inércia?

Se os desenvolvedores do Laravel construíssem SPAs da Web com Vue antes do Inertia, eles teriam que configurar APIs e retornar dados JSON com o Laravel e, em seguida, usar algo como AXIOS para recuperar os dados nos componentes do Vue. Eles também exigiriam algo como o Vue Router para gerenciar rotas, o que significaria perder o roteamento Laravel, bem como middlewares e controladores.

O Inertia.js, por outro lado, permite que os desenvolvedores criem aplicativos Vue, React e Svelte modernos de página única usando controladores e roteamento clássicos do lado do servidor. Inertia foi projetado para desenvolvedores de Laravel, Ruby on Rails e Django para permitir que eles criem aplicativos sem alterar suas técnicas de codificação de criar controladores, buscar dados de um banco de dados e renderizar visualizações

Graças ao Inertia.js, os desenvolvedores do Laravel se sentirão em casa.

Como funciona a inércia

Construir SPA apenas com Laravel e Vue fornecerá uma página JavaScript completa para o seu front-end, mas isso não fornecerá uma experiência de aplicativo de página única. Cada link clicado fará com que sua estrutura do lado do cliente seja reinicializada no próximo carregamento de página.

É aqui que a inércia entra em cena.

Inertia é basicamente uma biblioteca de roteamento do lado do cliente. Ele permite que você navegue entre as páginas sem precisar recarregar a página inteira. Isso é feito por meio do componente <Link> , que é um wrapper leve em torno de uma marca de âncora padrão.

Quando você clica em um link do Inertia, o Inertia intercepta o clique e o redireciona para o XHR. O navegador não recarregará a página dessa maneira, oferecendo ao usuário uma experiência completa de página única.

Começando com a inércia

Uma página simples com "Kinsta Blog" em um banner azul na parte superior e uma única linha de exemplos de cartões de artigo.
Uma página de amostra feita com Inertia.js

Para entender o Inertia e como integrá-lo ao Laravel, vamos construir um aplicativo da web de blog chamado Kinsta Blog usando a combinação mais poderosa, Laravel para o back-end, Vue.js para o front-end do JavaScript e Tailwind CSS para o estilo.

Se preferir seguir este tutorial em um ambiente local, você pode usar o DevKinsta, uma ferramenta poderosa para desenvolvedores, designers e agências que permite que eles construam aplicativos da web WordPress de uma ou várias páginas. Felizmente, o WordPress pode ser facilmente integrado ao Laravel usando o pacote Corcel.

Pré-requisitos

Para aproveitar ao máximo este tutorial, você deve estar familiarizado com o seguinte:

  • Noções básicas do Laravel (instalação, banco de dados, migrações de banco de dados, modelos Eloquent, controladores e roteamento)
  • Noções básicas do Vue.js (instalação, estrutura e formulários)

Se você está se sentindo inseguro, confira estes fantásticos tutoriais gratuitos e pagos do Laravel. Caso contrário, vamos pular.

Etapa um: instalar os elementos principais

Para focar no Inertia.js e ir direto para a parte divertida, certifique-se de ter a seguinte configuração pronta:

  1. Projeto Laravel 9 recém-instalado chamado kinsta-blog
  2. Tailwind CSS CLI instalado em nosso projeto Laravel
  3. Dois componentes blade em kinsta-blog/resources/views para visualizar a página inicial do blog e um único artigo no blog conforme mostrado abaixo:

    “/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>
  4. Banco de dados local MySQL chamado kinsta_blog conectado ao nosso projeto:

    .env “:

     DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=kinsta_blog DB_USERNAME=root DB_PASSWORD=
  5. Modelo de artigo, migrações e fábricas:

    “aplicativo/Modelos/ Artigo.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), ]; } }

Isso é tudo que precisamos para começar! Agora vamos ao que interessa e introduzir o Inertia.js em nosso projeto.

Passo 2: Instale o Inertia

O processo de instalação do Inertia é dividido em duas grandes fases: lado do servidor (Laravel) e lado do cliente (VueJs).

O guia de instalação oficial na documentação do Inertia está um pouco desatualizado porque o Laravel 9 agora usa o Vite por padrão, mas também veremos isso.

1. Lado do Servidor

A primeira coisa que precisamos fazer é instalar os adaptadores do lado do servidor Inertia com o comando de terminal abaixo via Composer.

 composer require inertiajs/inertia-laravel

Agora vamos configurar nosso modelo raiz, que será um único arquivo blade que será usado para carregar seus arquivos CSS e JS, bem como uma raiz Inertia que será usada para iniciar nosso aplicativo JavaScript.

Como estamos usando a versão mais recente do Laravel 9 v9.3.1, também devemos permitir que o Vite faça sua mágica incluindo-o em nossas tags em /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>

Observe como podemos buscar o título do projeto dinamicamente adicionando o atributo Inertia às tags <title> .

Também adicionamos a diretiva @vite ao cabeçalho para informar ao Vite o caminho do nosso arquivo principal JavaScript onde criamos nosso aplicativo e importamos nosso CSS. O Vite é uma ferramenta que ajuda no desenvolvimento de JavaScript e CSS, permitindo que os desenvolvedores visualizem as alterações do front-end sem precisar atualizar a página durante o desenvolvimento local.

Nosso próximo passo será criar o middleware HandleInertiaRequests e publicá-lo em nosso projeto. Podemos fazer isso disparando o comando do terminal abaixo no diretório raiz do nosso projeto:

 php artisan inertia:middleware

Depois de concluído, vá para “App/Http/ Kernel ” e registre HandleInertiaRequests como o último item em seus middlewares da web:

 'web' => [ // ... AppHttpMiddlewareHandleInertiaRequests::class, ],

2. Lado do cliente

Em seguida, temos que instalar nossas dependências frontend Vue.js 3 da mesma forma que no lado do servidor:

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

Em seguida, você precisa obter o Vue.js 3:

 npm install [email protected]

Em seguida, atualize seu arquivo JavaScript primário para inicializar Inertia.js com Vue.js 3, Vite e 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); }, });

No trecho de código acima, usamos o plugin resolvePageComponent do Laravel e dizemos a ele para resolver nossos componentes do diretório ./Pages/$name.vue . Isso ocorre porque salvaremos nossos componentes de inércia neste diretório posteriormente em nosso projeto, e este plug-in nos ajudará a carregar automaticamente esses componentes do diretório correto.

Tudo o que resta é instalar o vitejs/plugin-vue :

 npm i @vitejs/plugin-vue

E atualize o arquivo vite.config.js :

 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, }, }, }), ], });

A etapa final é instalar nossas dependências e compilar nossos arquivos:

 npm install npm run dev

E voilá! Você tem um aplicativo Laravel 9 funcional com Vue.js 3 e Vite. Agora precisamos ver algo acontecendo em ação!

Criando páginas de inércia

Você se lembra daqueles dois arquivos blade ( index e show ) para visualizar nossa página inicial e um único artigo?

O único arquivo blade de que precisaremos ao usar o Inertia é app.blade.php , que já usamos uma vez quando estávamos instalando o Inertia. Então, o que acontece com esses arquivos agora?

Vamos transformar esses arquivos de componentes blade em componentes Inertia.js.

Cada página em seu aplicativo tem seu próprio controlador e componente JavaScript com Inertia. Isso permite obter apenas os dados necessários para essa página, sem usar uma API. As páginas de inércia nada mais são do que componentes JavaScript, no nosso caso, são componentes Vue.js. Eles não têm nada particularmente notável sobre eles. Então, o que faremos é agrupar todo o conteúdo HTML entre as tags <template> e qualquer coisa relacionada ao JavaScript será agrupada com as tags <script> .

Crie uma pasta chamada “Páginas” e mova seus arquivos para lá. Então teremos “ index.blade.php ” e “ show.blade.php ” em “ ./resources/js/Pages “. Em seguida, alteraremos o formato do arquivo para “.vue” em vez de “.blade.php” enquanto colocamos a primeira letra de seus nomes em maiúscula e transformamos seu conteúdo em um componente Vue.js padrão. Excluiremos as tags <html> , <head> e <body> porque elas já estão incluídas no componente blade raiz principal.

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

Há algo realmente me incomodando! Continuamos copiando e colando nosso cabeçalho e rodapé em cada componente, o que não é uma boa prática. Vamos criar um Layout básico do Inertia para armazenar nossos componentes persistentes.

Crie uma pasta chamada “Layouts” em “ /resources/js ” e dentro dessa pasta crie um arquivo chamado “KinstaLayout.vue”. Este arquivo terá nosso cabeçalho e rodapé e o main com um <slot /> para permitir que todos os componentes agrupados com este layout sejam embutidos nele. Este arquivo deve ficar assim:

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

Em seguida, vamos importar esse novo layout em nossas páginas e agrupar todo o conteúdo HTML com ele. Nossos componentes devem ficar assim:

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>

Rotas Laravel e Renderização de Inércia

Primeiro, vamos usar o arquivo “ ArticleFactory ” que temos do ponto de partida do nosso tutorial e semear alguns artigos em nosso banco de dados.

“banco de dados/semeadores/ banco de dadosSeeder.php “:

 <?php namespace DatabaseSeeders; use AppModelsArticle; use IlluminateDatabaseSeeder; class DatabaseSeeder extends Seeder { public function run() { Article::factory(10)->create(); } }

Em seguida, pressione o comando do terminal abaixo para migrar suas tabelas e semear os dados falsos das fábricas:

 php artisan migrate:fresh --seed

Isso criará 10 artigos falsos no banco de dados, que precisaremos passar para nossa visualização usando o roteamento do Laravel. Agora que estamos usando o Inertia para renderizar visualizações, a maneira como usamos para escrever nossas rotas mudará um pouco. Vamos criar nossa primeira rota Laravel Inertia em “routes/ web.php ” e retornar a visualização da página inicial em “/resources/js/Pages/ Index.vue ”.

“rotas/ web.php “:

 <?php use AppModelsArticle; use IlluminateSupportFacadesRoute; use InertiaInertia; Route::get('/', function () { return Inertia::render('Index', [ 'articles' => Article::latest()->get() ]); })->name('home');

Observe que importamos Inertia e não usamos o auxiliar view() Laravel para retornar a exibição, mas usamos Inertia::render . O Inertia também procurará por padrão o nome do arquivo que mencionamos em nossa rota na pasta Pages em “resources/js”.

Vá para o arquivo de índice e defina os dados recuperados como prop e faça um loop sobre eles com v-for para mostrar os resultados. Entre as tags de script, defina os dados passados ​​como prop. Tudo o que o Inertia precisa saber é que tipo de dados você está esperando, que no nosso caso é um objeto 'Artigo' contendo uma matriz de artigos.

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

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; defineProps({ Articles: Object, }); </script>

Observe que é suficiente apenas defini-lo como um prop sem retorná-lo porque estamos usando o formato de setup para a API de composição do Vue.js 3. Se estivermos usando a API de opções, precisaremos retorná-la.

Vamos fazer o loop:

 <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 (deixe rodando porque estamos usando o Vite) e php artisan serve para iniciar o servidor de desenvolvimento laravel e acessar nosso site, veremos a página esperada exibindo todos os dez artigos no banco de dados.

Agora, estamos usando a extensão Vue DevTools do Google Chrome, que nos permite depurar meu aplicativo. Vamos mostrar como nossos dados estão sendo passados ​​para o componente.

Extensão Vue DevTools do Chrome mostrando uma lista de propriedades de inércia para a página aberta.
Inspecionando as propriedades de inércia.

“Artigos” é passado para o componente como um objeto prop contendo uma matriz de artigos; cada artigo no array também é um objeto com propriedades que correspondem aos dados que ele adquiriu do banco de dados. Isso significa que qualquer dado que transferirmos do Laravel para o Inertia será tratado como prop.

Usando Tailwind CSS com Inertia.js

Como o Tailwind já está instalado em nosso projeto no ponto de partida, tudo o que precisamos fazer é dizer a ele para ler nossos componentes de inércia. Isso pode ser feito editando “ tailwind.config.js ” da seguinte forma:

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

Em seguida, verifique se importamos nosso arquivo CSS em “resources/js/ app.js ”:

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

E agora estamos prontos para estilizar nossos componentes.

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

Se você olhar no navegador, notará que o Vite já atualizou a página com a magia Tailwind.

Uma imagem de rolagem mostrando uma versão funcional do exemplo anterior do "Kinsta Blog".
Renderizando propriedades de inércia.

Ligações de Inércia

Agora que temos uma página inicial funcional que pode exibir todos os artigos do banco de dados, precisamos criar outra rota para exibir artigos individuais. Vamos criar uma nova rota e definir a URL como um curinga “id”:

“rotas/ 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');

Importamos o modelo “Artigo” e adicionamos uma nova rota para retornar o componente Show.vue Inertia. Também aproveitamos a vinculação do modelo de rota do Laravel, que permite que o Laravel obtenha automaticamente o artigo ao qual estamos nos referindo.

Tudo o que precisamos agora é uma maneira de visitar esta rota clicando em um link da página inicial sem precisar recarregar a página inteira. Isso é possível com a ferramenta mágica <Link> da Inertia. Mencionamos na introdução que o Inertia usa <Link> como um wrapper para uma tag de âncora padrão <a> , e que esse wrapper visa tornar as visitas à página o mais simples possível. Em Inertia, a tag <Link> pode se comportar como uma tag âncora que realiza requisições <GET> , mas também pode atuar como um <button> e um <form> ao mesmo tempo. Vamos ver como podemos aplicá-lo ao nosso projeto.

Em nosso Index.vue, vamos importar <Link> de Inertia e remover as tags âncora <a> e substituí-las por tags Inertia <Link> . O atributo href será definido para o URL da rota que fizemos anteriormente para visualizar o artigo:

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

Vamos estilizar Show.vue com Tailwind para deixá-lo um pouco mais arrumado e pronto para nossa visita. E também precisamos deixá-lo saber que deve esperar um objeto “Artigo” e defini-lo como um suporte:

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

Agora, quando clicarmos no título do artigo ou em “Leia mais”, seremos transportados magicamente para o Show.vue sem atualizar a página.

Lutando com problemas de tempo de inatividade e WordPress? Kinsta é a solução de hospedagem projetada para economizar seu tempo! Confira nossos recursos
A página de exemplo "Kinsta Blog" mostrando cartões de artigo com links de trabalho.
Links de inércia no lugar.

No nosso caso, estamos usando <Link> como uma tag âncora que envia uma solicitação GET para a rota e retorna os novos dados, mas podemos usar <Link> para também POST , PUT , PATCH e DELETE

“rotas/ web.php “:

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

Dicas e truques de inércia do Laravel que você deve saber

Agora temos um SPA funcional construído com Laravel, Inertia e Tailwind CSS. Mas a inércia pode nos ajudar a alcançar muito mais. É hora de adquirir algumas técnicas de Inércia que ajudarão tanto os desenvolvedores quanto os visitantes do aplicativo.

Gerando URLs

Você deve ter notado que adicionamos nomes às nossas rotas do Laravel sem usá-los. A inércia nos permite usar nossas rotas nomeadas em nossos componentes, em vez de anotar manualmente a rota completa.

Podemos conseguir isso instalando o pacote Ziggy em nosso projeto:

 composer require tightenco/ziggy

Em seguida, vá para “resources/js/app.js” e atualize-o assim:

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

Vá para “/resources/views/ app.blade.php ” e atualize o cabeçalho com a diretiva @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>

…e atualize seus pacotes NPM pressionando os dois comandos de terminal abaixo:

 npm install && npm run dev

Este pacote nos permite usar rotas nomeadas dentro de nossos componentes Inertia, então vamos ao Index.vue e removemos a antiga rota manual e a substituímos pelo nome da rota enquanto passamos os dados normalmente como se estivéssemos em nosso controlador.

Vamos substituir isso:

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

…com isso:

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

Isso nos dará exatamente o mesmo comportamento que tivemos, mas é mais amigável ao desenvolvedor e extremamente útil quando sua rota espera muitos parâmetros.

Indicadores de Progresso

Este é um dos melhores recursos do Inertia.js; como o SPA fornece uma experiência de usuário interativa, ter feedback constante sobre o carregamento de uma solicitação seria uma adição fantástica ao aplicativo. Isso pode ser feito por uma biblioteca separada que a Inertia está oferecendo.

A biblioteca “@inertiajs/progress” é um wrapper em torno do NProgress que mostra condicionalmente os indicadores de carregamento de acordo com os eventos de inércia. Você realmente não precisa saber como isso funciona nos bastidores, então vamos fazer funcionar.

Podemos instalar esta biblioteca com o comando de terminal abaixo:

 npm install @inertiajs/progress

Uma vez instalado, precisamos importá-lo em “ 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 });

Isso mostrará uma barra de carregamento e um botão giratório de carregamento na cor preta, mas podemos alterar a cor junto com outras opções úteis que podem ser encontradas na documentação do indicador de progresso do Inertia.js.

O cabeçalho azul "Kinsta Blog" com o indicador giratório no canto superior direito.
O indicador de progresso de inércia (canto superior direito).

Gerenciamento de rolagem

Em alguns casos, você pode querer navegar para uma nova página enquanto mantém a mesma posição de rolagem. Talvez você precise disso se permitir que os usuários deixem comentários; isso enviará um formulário e carregará o novo comentário do banco de dados em seu componente; você deseja que isso aconteça sem que o usuário perca a posição de rolagem. A inércia cuida disso para nós.

No nosso caso, vamos aplicar isso à nossa tag <Link> em Index.vue . Para preservar a posição de rolagem enquanto redireciona para uma página diferente com o <Link> do Inertia, tudo o que precisamos fazer é adicionar o atributo preserve-scroll ao <Link> :

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

dicas de SEO

Desde o nascimento dos SPAs, as pessoas se preocupam com a otimização de mecanismos de busca (SEO). É sabido que, se você usar a abordagem SPA, os mecanismos de pesquisa terão dificuldade em rastrear seu aplicativo da web porque tudo é renderizado no lado do cliente, resultando em seu site não aparecendo na parte superior dos resultados da pesquisa; no entanto, como essas plataformas populares como Facebook e Github agora são SPAs e ainda têm um bom desempenho em SEO?

Bem, esta não é uma missão: impossível mais. A Inertia está oferecendo algumas soluções para ajudar seu SPA a se tornar SEO amigável.

Inertia Vue SSR com Laravel e Vite

Os mecanismos de pesquisa estão sempre procurando por HTML em seu site para identificar o conteúdo; no entanto, se você não tiver HTML em suas URLs, esse trabalho fica mais difícil. Ao desenvolver SPAs, tudo o que você tem em sua página é JavaScript e JSON. A inércia introduziu um recurso de renderização no lado do servidor (SSR) que você pode adicionar ao seu aplicativo. Isso permite que seu aplicativo pré-renderize uma visita de página inicial no servidor e, em seguida, envie o HTML renderizado para o navegador. Isso permite que os usuários vejam e interajam com suas páginas antes que elas carreguem totalmente, além de ter outras vantagens, como reduzir o tempo que os mecanismos de pesquisa levam para indexar seu site.

Para resumir como funciona, o Inertia identificará se está sendo executado em um servidor Node.js e renderizará os nomes dos componentes, propriedades, URL e versão dos ativos em HTML. Isso fornecerá ao usuário e ao mecanismo de pesquisa praticamente tudo o que sua página tem a oferecer.

No entanto, como estamos lidando com o Laravel, isso faz pouco sentido porque o Laravel é um framework PHP e não roda em um servidor Node.js. Portanto, encaminharemos a solicitação para um serviço Node.js, que renderizará a página e retornará o HTML. Isso tornará nosso aplicativo Laravel Vue amigável para SEO por padrão.

Primeiro, precisamos instalar o pacote Vue.js SSR npm:

 npm install @vue/server-renderer

Another helpful Inertia “NPM” package provides a simple “HTTP” server. It is strongly recommended that you install it:

 npm install @inertiajs/server

Then, in “resources/js/”, we'll add a new file named ssr.js . This file will be very similar to the app.js file we created when installing Inertia, only it will execute in Node.js rather than 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 since it will not be visible to visitors; this file is only for search engines and browsers to show the data within your page, so include only what is important to your data or only what will make your data available.

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

The Inertia.js DOCs aren't explaining how to integrate Inertia SSR with Vite, but we will go through this now. Head to vite.config.js and paste the below:

 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, head to package.json and change the build script:

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

Now if we run npm run build , Vite will build our SSR bundle for production. For more information about this you may visit Inertia SSR DOCs and Vite SSR DOCs.

Title and Meta

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

To add <head> element to your Page, we must import <head> from Inertia same as we did with <Link> component:

import { Head } from '@inertiajs/inertia-vue3' <Head> <title>Kinsta Blog</title> <meta name="description" content="Kinsta blog for developers"> </Head>

Também podemos adicionar um título global para todas as páginas, isso adicionará o nome do seu aplicativo ao lado do título em todas as páginas. Já fizemos isso no arquivo app.js :

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

O que significa que se adicionarmos <head title="Homepage"> na página inicial de nosso aplicativo com um título, isso será renderizado assim: <title>Home - My App</title> .

Monitorando seu aplicativo

A velocidade é um dos fatores mais importantes para otimizar o desempenho de SEO em seu site. Se você usa o WordPress para o seu site, por esse motivo, o Kinsta APM o ajudará a monitorar e acompanhar de perto o seu aplicativo em ação. Ele ajuda você a identificar problemas de desempenho do WordPress e está disponível gratuitamente em todos os sites hospedados em Kinsta.

Resumo

Inertia.js é uma das tecnologias mais importantes disponíveis; misture-o com o Laravel e você terá um aplicativo moderno de página única construído com PHP e JavaScript. Taylor Otwell, o criador do Laravel, está tão interessado no Inertia que o Laravel lançou seus starter kits mais populares, Laravel Breeze e Jetstream, com suporte para Inertia e SSR.
Veja como você pode começar a usar o Inertia.js e como usá-lo com Laravel, Vue.js e Tailwind CSS para criar um moderno ap de blog neste guia Click to Tweet
Se você é um fã do Laravel ou um desenvolvedor profissional, o Inertia.js sem dúvida chamará sua atenção. Neste tutorial, criamos um blog muito básico e direto em apenas alguns minutos. Ainda há muito o que aprender sobre inércia, e este pode ser apenas o primeiro de muitos artigos e tutoriais.

O que mais sobre o Laravel você gostaria que explorássemos? Deixe-nos saber na seção de comentários abaixo.