Как использовать Inertia.js в ваших проектах Laravel

Опубликовано: 2022-12-08

Многостраничные приложения (MPA) с каждым днем ​​становятся все менее популярными. Известные платформы, такие как Facebook, Twitter, YouTube, Github и многие другие, уже используют технологию одностраничных приложений (SPA).

Эта модная технология позволяет пользователям взаимодействовать с веб-приложениями быстро и оперативно, поскольку все обрабатывается на стороне клиента. Тем не менее, это может быть проблемой для разработчиков, которые создают приложения для рендеринга на стороне сервера с такими фреймворками, как Laravel или Django.

К счастью, Inertia.js вмешался и пришел на помощь.
Недостающий ингредиент, который нужен вашим проектам Laravel? Инерция.js. Узнайте больше в этом подробном руководстве Click to Tweet
В этой статье мы покажем, как начать работу с Inertia.js и как использовать его с Laravel, Vue.js и Tailwind CSS для создания современного веб-приложения для блога. Мы также расскажем, как сделать SPA более оптимизированными для SEO, а также расскажем о нескольких других хитростях.

Если вы только начинаете работать с Laravel, мы рекомендуем вам сначала прочитать эту статью, чтобы вы были готовы к работе.

Почему СПА?

Прежде чем мы сможем спросить, почему мы должны использовать Inertia, мы должны сначала спросить: «Почему SPA?»

Почему кто-то предпочитает клиентские приложения с визуализацией традиционным серверным приложениям? Что заставит разработчика полного стека Laravel попрощаться с блейд-компонентами?

Короткий ответ: потому что скорость и отзывчивость необходимы для любого успешного взаимодействия с пользователем.

В случае MPA браузер постоянно отправляет запросы на серверную часть, которая затем выполняет многочисленные запросы к базе данных. После того как база данных и сервер обрабатывают запросы и доставляют их в браузер, страница визуализируется.

Но СПА бывают разные. Приложение переносит все, что может потребоваться пользователю, прямо на страницу, избавляя браузер от необходимости отправлять запросы или перезагружать страницу для отображения новых элементов HTML.

Из-за этого уникального пользовательского опыта многие известные компании требуют, чтобы их веб-сайты стали одностраничными приложениями.

При этом создание одностраничного приложения может быть трудным для разработчиков Laravel, потому что им потребуется начать использовать Vue.js или React вместо шаблонов блейдов, что приведет к потере многих драгоценных камней Laravel, которые экономят время и усилия.

Однако теперь, когда у нас есть Inertia.js, все изменилось.

Почему инерция?

Если бы разработчики Laravel создавали веб-SP с помощью Vue до Inertia, им пришлось бы настраивать API и возвращать данные JSON с помощью Laravel, а затем использовать что-то вроде AXIOS для извлечения данных в компонентах Vue. Им также потребуется что-то вроде Vue Router для управления маршрутами, что будет означать потерю маршрутизации Laravel, а также промежуточного программного обеспечения и контроллеров.

Inertia.js, с другой стороны, позволяет разработчикам создавать современные одностраничные приложения Vue, React и Svelte, используя классическую маршрутизацию и контроллеры на стороне сервера. Inertia была разработана для разработчиков Laravel, Ruby on Rails и Django, чтобы позволить им создавать приложения, не меняя свои методы кодирования для создания контроллеров, выборки данных из базы данных и рендеринга представлений.

Благодаря Inertia.js разработчики Laravel будут чувствовать себя как дома.

Как работает инерция

Создание SPA только с Laravel и Vue даст вам полноценную страницу JavaScript для вашего внешнего интерфейса, но это не даст вам одностраничного приложения. Каждая щелкнутая ссылка приведет к перезагрузке вашей клиентской среды при загрузке следующей страницы.

Здесь на сцену выходит инерция.

Inertia — это, по сути, библиотека маршрутизации на стороне клиента. Это позволяет вам перемещаться между страницами без перезагрузки всей страницы. Это достигается с помощью компонента <Link> , который представляет собой облегченную оболочку стандартного тега привязки.

Когда вы щелкаете ссылку Inertia, Inertia перехватывает щелчок и вместо этого перенаправляет вас на XHR. Браузер не будет перезагружать страницу таким образом, предоставляя пользователю полноценный одностраничный интерфейс.

Начало работы с инерцией

Простая страница с «Блогом Kinsta» в синем баннере вверху и одним рядом карточек с образцами статей.
Пример страницы, созданной с помощью Inertia.js

Чтобы понять Inertia и как интегрировать ее с Laravel, мы собираемся создать веб-приложение блога под названием Kinsta Blog , используя самую мощную комбинацию, Laravel для серверной части, Vue.js для внешнего интерфейса JavaScript и Tailwind CSS для стилей.

Если вы предпочитаете следовать этому руководству в локальной среде, вы можете использовать DevKinsta, мощный инструмент для разработчиков, дизайнеров и агентств, который позволяет им создавать одно- и многостраничные веб-приложения WordPress. К счастью, WordPress можно легко интегрировать с Laravel с помощью пакета Corcel.

Предпосылки

Чтобы получить максимальную отдачу от этого руководства, вы должны быть знакомы со следующим:

  • Основы Laravel (установка, база данных, миграция баз данных, модели Eloquent, контроллеры и маршрутизация)
  • Основы Vue.js (установка, структура и формы)

Если вы не уверены, ознакомьтесь с этими фантастическими бесплатными и платными учебными пособиями по Laravel. В противном случае, давайте прыгать.

Шаг первый: установите основные элементы

Чтобы сосредоточиться на Inertia.js и сразу перейти к самой интересной части, убедитесь, что у вас есть готовые следующие настройки:

  1. Недавно установленный проект Laravel 9 под названием kinsta-blog
  2. Tailwind CSS CLI, установленный в нашем проекте Laravel
  3. Два блейд-компонента в kinsta-blog/resources/views для просмотра домашней страницы блога и одной статьи в блоге, как показано ниже:

    « /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. Локальная база данных MySQL с именем kinsta_blog подключена к нашему проекту:

    « .env »:

     DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=kinsta_blog DB_USERNAME=root DB_PASSWORD=
  5. Модель статьи, миграции и фабрики:

    «приложение/Модели/ Статья.php »:

     <?php namespace AppModels; use IlluminateDatabaseEloquentFactoriesHasFactory; use IlluminateDatabaseEloquentModel; class Article extends Model { use HasFactory; protected $fillable = ['title', 'excerpt', 'body']; }

    «база данных/миграции/ 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'); } };

    «база данных/фабрики/ 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), ]; } }

Это все, что нам нужно для начала! Теперь давайте приступим к делу и познакомим Inertia.js с нашим проектом.

Шаг 2: Установите инерцию

Процесс установки Inertia разделен на две основные фазы: серверная (Laravel) и клиентская (VueJs).

Официальное руководство по установке в документации Inertia немного устарело, потому что Laravel 9 теперь использует Vite по умолчанию, но мы рассмотрим и это.

1. Серверная часть

Первое, что нам нужно сделать, это установить серверные адаптеры Inertia с помощью приведенной ниже команды терминала через Composer.

 composer require inertiajs/inertia-laravel

Теперь мы настроим наш корневой шаблон, который будет представлять собой один блейд-файл, который будет использоваться для загрузки ваших файлов CSS и JS, а также корень Inertia, который будет использоваться для запуска нашего приложения JavaScript.

Поскольку мы используем самую последнюю версию Laravel 9 v9.3.1, мы также должны позволить Vite творить чудеса, включив его в наши теги в /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>

Обратите внимание, как мы можем динамически получать название проекта, добавляя атрибут Inertia к тегам <title> .

Мы также добавили директиву @vite в заголовок, чтобы сообщить Vite путь к нашему основному файлу JavaScript, в котором мы создали наше приложение и импортировали наш CSS. Vite — это инструмент, который помогает в разработке JavaScript и CSS, позволяя разработчикам просматривать изменения во внешнем интерфейсе без необходимости обновлять страницу во время локальной разработки.

Нашим следующим шагом будет создание промежуточного ПО HandleInertiaRequests и его публикация в нашем проекте. Мы можем сделать это, выполнив следующую команду терминала в корневом каталоге нашего проекта:

 php artisan inertia:middleware

Как только это будет завершено, перейдите в «App/Http/ Kernel » и зарегистрируйте HandleInertiaRequests как последний элемент в вашем веб-промежуточном программном обеспечении:

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

2. Клиентская сторона

Затем мы должны установить наши внешние зависимости Vue.js 3 так же, как и на стороне сервера:

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

Далее вам нужно загрузить Vue.js 3:

 npm install [email protected]

Затем обновите свой основной файл JavaScript, чтобы инициализировать Inertia.js с помощью Vue.js 3, Vite и Laravel:

«ресурсы/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); }, });

В приведенном выше фрагменте кода мы используем плагин Laravel resolvePageComponent и сообщаем ему разрешить наши компоненты из каталога ./Pages/$name.vue . Это связано с тем, что мы будем сохранять наши компоненты Inertia в этом каталоге позже в нашем проекте, и этот плагин поможет нам автоматически загружать эти компоненты из правильного каталога.

Осталось установить vitejs/plugin-vue :

 npm i @vitejs/plugin-vue

И обновите файл 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, }, }, }), ], });

Последний шаг — установить наши зависимости и скомпилировать наши файлы:

 npm install npm run dev

И вуаля! У вас есть работающее приложение Laravel 9 с Vue.js 3 и Vite. Теперь нам нужно увидеть что-то происходящее в действии!

Создание страниц инерции

Вы помните эти два блейд-файла ( index и show ) для просмотра нашей домашней страницы и одной статьи?

Единственный блейд-файл, который нам понадобится при использовании Inertia, — это app.blade.php , который мы уже использовали один раз при установке Inertia. Что теперь происходит с этими файлами?

Мы преобразуем эти файлы из блейд-компонентов в компоненты Inertia.js.

Каждая страница в вашем приложении имеет свой собственный контроллер и компонент JavaScript с Inertia. Это позволяет вам получать только данные, необходимые для этой страницы, без использования API. Страницы инерции — это не что иное, как компоненты JavaScript, в нашем случае это компоненты Vue.js. Ничего особо примечательного в них нет. Итак, что мы будем делать, так это обернуть весь HTML-контент между тегами <template> , а все, что связано с JavaScript, будет заключено в теги <script> .

Создайте папку под названием «Страницы» и переместите туда файлы. Итак, у нас будут « index.blade.php » и « show.blade.php » в « ./resources/js/Pages ». Затем мы изменим формат файла на «.vue» вместо «.blade.php», сделав первую букву их имен прописными, и превратим его содержимое в стандартный компонент Vue.js. Мы исключим теги <html> , <head> и <body> , так как они уже включены в основной корневой блейд-компонент.

«ресурсы/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>

«ресурсы/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>

Меня что-то очень беспокоит! Мы продолжаем копировать и вставлять наш верхний и нижний колонтитулы в каждый компонент, что является не очень хорошей практикой. Давайте создадим базовый макет Inertia для хранения наших постоянных компонентов.

Создайте папку «Layouts» в « /resources/js » и внутри этой папки создайте файл с именем «KinstaLayout.vue». Этот файл будет иметь наши верхний и нижний колонтитулы, а также main с <slot /> , чтобы все компоненты, заключенные в этот макет, могли быть встроены в него. Этот файл должен выглядеть так:

«ресурсы/JS/Макеты/ 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>

Затем мы собираемся импортировать этот новый макет на наши страницы и обернуть им весь HTML-контент. Наши компоненты должны выглядеть так:

Индекс.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>

Показать.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>

Laravel Routes и Inertia Render

Сначала давайте воспользуемся файлом « ArticleFactory », который у нас есть из начальной точки нашего руководства, и загрузим несколько статей в нашу базу данных.

«база данных/сидеры/ databaseSeeder.php »:

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

Затем нажмите приведенную ниже команду терминала, чтобы перенести ваши таблицы и заполнить поддельные данные с фабрик:

 php artisan migrate:fresh --seed

Это создаст 10 поддельных статей в базе данных, которые нам нужно будет передать нашему представлению с помощью маршрутизации Laravel. Теперь, когда мы используем Inertia для рендеринга представлений, способ, которым мы писали наши маршруты, немного изменится. Давайте создадим наш первый маршрут Laravel Inertia в «routes/ web.php » и вернем представление домашней страницы из « /resources/js/Pages/Index.vue ».

«маршруты/ web.php »:

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

Обратите внимание, что мы импортировали Inertia и не использовали хелпер view() Laravel для возврата представления, а вместо этого использовали Inertia::render . Inertia также по умолчанию будет искать имя файла, которое мы упомянули в нашем маршруте, в папке Pages в «resources/js».

Перейдите к индексному файлу и установите извлеченные данные в качестве опоры и переберите их с помощью v-for , чтобы показать результаты. Между тегами script определите переданные данные как опору. Все, что нужно знать Inertia, — это тип данных, которые вы ожидаете, в нашем случае это объект «Статья», содержащий массив статей.

«ресурсы/js/Pages/ Index.vue »:

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

Обратите внимание, что достаточно только определить его как свойство, не возвращая его, потому что мы используем формат setup для Vue.js 3 API композиции. Если мы используем API опций, нам нужно будет вернуть его.

Делаем петлю:

 <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 (оставьте его работающим, потому что мы используем Vite) и php artisan serve для запуска сервера разработки laravel и доступа к нашему веб-сайту, мы увидим ожидаемую страницу, отображающую все десять статей в базе данных.

Теперь мы используем расширение Google Chrome Vue DevTools, которое позволяет нам отлаживать мое приложение. Давайте покажем вам, как наши данные передаются компоненту.

Расширение Chrome Vue DevTools, показывающее список свойств Inertia для открытой страницы.
Проверка свойств инерции.

«Статьи» передаются компоненту в виде объекта prop, содержащего массив статей; каждая статья в массиве также является объектом со свойствами, соответствующими данным, полученным из базы данных. Это означает, что любые данные, которые мы передаем из Laravel в Inertia, будут рассматриваться как реквизит.

Использование Tailwind CSS с Inertia.js

Поскольку Tailwind уже установлен в нашем проекте в начальной точке, все, что нам нужно сделать, это сказать ему, чтобы он читал наши компоненты Inertia. Этого можно добиться, отредактировав « tailwind.config.js » следующим образом:

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

Затем убедитесь, что мы импортировали наш файл CSS в «resources/js/ app.js »:

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

И теперь мы готовы стилизовать наши компоненты.

«ресурсы/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>

«ресурсы/JS/Макеты/ 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>

Если вы посмотрите в браузере, вы заметите, что Vite уже обновил страницу с помощью магии Tailwind.

Прокручивающееся изображение, показывающее функционирующую версию примера «Блог Kinsta» из предыдущего.
Отрисовка свойств инерции.

Инерционные ссылки

Теперь, когда у нас есть рабочая домашняя страница, которая может отображать все статьи в базе данных, нам нужно создать еще один маршрут для отображения отдельных статей. Давайте создадим новый маршрут и установим URL-адрес в подстановочный знак «id»:

«маршруты/ 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');

Мы импортировали модель «Статья» и добавили новый маршрут для возврата компонента Show.vue Inertia. Мы также использовали привязку модели маршрута Laravel, которая позволяет Laravel автоматически получать статью, на которую мы ссылаемся.

Все, что нам нужно сейчас, — это способ посетить этот маршрут, щелкнув ссылку на главной странице, без перезагрузки всей страницы. Это возможно с помощью волшебного инструмента Inertia <Link> . Во введении мы упоминали, что Inertia использует <Link> в качестве оболочки для стандартного тега привязки <a> и что эта оболочка предназначена для максимально плавного посещения страниц. В Inertia <Link> может вести себя как тег привязки, который выполняет запросы <GET> , но он также может действовать как <button> и <form> одновременно. Давайте посмотрим, как мы можем применить это к нашему проекту.

В нашем Index.vue мы импортируем <Link> из Inertia, удаляем теги привязки <a> и заменяем их тегами Inertia <Link> . Атрибут href будет установлен на URL-адрес маршрута, который мы ранее сделали для просмотра статьи:

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

Давайте стилизуем Show.vue с помощью Tailwind, чтобы он выглядел более нарядным и готовым к нашему визиту. А также нам нужно сообщить ему, что он должен ожидать объект «Статья», и установить его в качестве реквизита:

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

Теперь, когда мы нажимаем на заголовок статьи или «Подробнее», мы волшебным образом переносимся на Show.vue без обновления страницы.

Боретесь с простоями и проблемами WordPress? Kinsta — это решение для хостинга, предназначенное для экономии вашего времени! Ознакомьтесь с нашими возможностями
Пример страницы «Блог Kinsta», на которой показаны карточки статей с рабочими ссылками.
Инерционные звенья на месте.

В нашем случае мы используем <Link> в качестве тега привязки, который отправляет запрос GET на маршрут и возвращает новые данные, но мы можем использовать <Link> также для POST , PUT , PATCH и DELETE

«маршруты/ web.php »:

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

Советы и хитрости Laravel Inertia, которые вы должны знать

Теперь у нас есть рабочий SPA, созданный с помощью Laravel, Inertia и Tailwind CSS. Но инерция может помочь нам достичь гораздо большего. Пришло время освоить некоторые приемы Inertia, которые помогут как разработчикам, так и посетителям приложений.

Создание URL-адресов

Возможно, вы заметили, что мы добавляем имена к нашим маршрутам Laravel, не используя их. Инерция позволяет нам использовать наши именованные маршруты в наших компонентах вместо того, чтобы вручную записывать полный маршрут.

Мы можем добиться этого, установив пакет Ziggy в наш проект:

 composer require tightenco/ziggy

Затем перейдите в «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"; 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); }, });

Перейдите в « /resources/views/app.blade.php » и обновите заголовок директивой @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>

… и обновите свои пакеты NPM, выполнив следующие две команды терминала:

 npm install && npm run dev

Этот пакет позволяет нам использовать именованные маршруты в наших компонентах Inertia, поэтому давайте перейдем к Index.vue и удалим старый ручной маршрут и заменим его именем маршрута, передавая данные в обычном режиме, как если бы мы были в нашем контроллере.

Мы заменим это:

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

…с этим:

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

Это даст нам то же поведение, что и у нас, но более удобно для разработчиков и чрезвычайно полезно, когда ваш маршрут ожидает много параметров.

Индикаторы прогресса

Это одна из самых приятных особенностей Inertia.js; поскольку SPA обеспечивает интерактивный пользовательский интерфейс, постоянная обратная связь о том, загружается ли запрос, была бы фантастическим дополнением к приложению. Этого можно добиться с помощью отдельной библиотеки, которую предлагает Inertia.

Библиотека «@inertiajs/progress» — это оболочка над NProgress, которая условно показывает индикаторы загрузки в соответствии с событиями Inertia. Вам действительно не нужно знать, как это работает за кулисами, так что давайте просто заставим это работать.

Мы можем установить эту библиотеку с помощью следующей команды терминала:

 npm install @inertiajs/progress

После установки нам нужно импортировать его в « 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 });

Это покажет полосу загрузки и счетчик загрузки в черном цвете, но мы можем изменить цвет вместе с другими полезными параметрами, которые можно найти в документации индикатора прогресса Inertia.js.

Синий заголовок «Блог Kinsta» с вращающимся индикатором вверху справа.
Индикатор прогресса инерции (вверху справа).

Управление прокруткой

В некоторых случаях может потребоваться перейти на новую страницу, сохраняя ту же позицию прокрутки. Возможно, вам это понадобится, если вы разрешите пользователям оставлять комментарии; это отправит форму и загрузит новый комментарий из базы данных в ваш компонент; вы хотите, чтобы это произошло без потери позиции прокрутки пользователем. Инерция позаботится об этом за нас.

В нашем случае давайте применим это к нашему тегу <Link> в Index.vue . Чтобы сохранить положение прокрутки при перенаправлении на другую страницу с помощью <Link> Inertia, все, что нам нужно сделать, это добавить атрибут preserve-scroll к <Link> :

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

Советы по SEO

С момента рождения SPA люди были обеспокоены поисковой оптимизацией (SEO). Общеизвестно, что если вы используете подход SPA, поисковым системам будет трудно сканировать ваше веб-приложение, потому что все отображается на стороне клиента, в результате чего ваш веб-сайт не отображается в верхней части результатов поиска; тем не менее, почему такие популярные платформы, как Facebook и Github, теперь являются SPA и по-прежнему хорошо работают в SEO?

Ну, это не миссия: больше невозможно. Inertia предлагает несколько решений, которые помогут вашему SPA стать оптимизированным для SEO.

Inertia Vue SSR с Laravel и Vite

Поисковые системы всегда ищут HTML на вашем веб-сайте, чтобы идентифицировать контент; однако, если в ваших URL-адресах нет HTML, эта работа усложняется. При разработке SPA все, что у вас есть на вашей странице, — это JavaScript и JSON. Inertia представила функцию рендеринга на стороне сервера (SSR), которую вы можете добавить в свое приложение. Это позволяет вашему приложению предварительно отображать начальное посещение страницы на сервере, а затем отправлять обработанный HTML-код в браузер. Это позволяет пользователям видеть ваши страницы и взаимодействовать с ними до того, как они полностью загрузятся, а также имеет другие преимущества, такие как сокращение времени, которое требуется поисковым системам для индексации вашего сайта.

Подводя итог, как это работает, Inertia определит, работает ли он на сервере Node.js, и отобразит имена компонентов, свойства, URL-адрес и версию ресурсов в HTML. Это предоставит пользователю и поисковой системе практически все, что может предложить ваша страница.

Однако, поскольку мы имеем дело с Laravel, в этом мало смысла, поскольку Laravel — это PHP-фреймворк, который не работает на сервере Node.js. Поэтому мы перенаправим запрос в службу Node.js, которая отобразит страницу и вернет HTML. Это сделает наше приложение Laravel Vue оптимизированным для SEO по умолчанию.

Во-первых, нам нужно установить пакет 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>

Мы также можем добавить глобальный заголовок для всех страниц, это добавит имя вашего приложения рядом с заголовком на каждой странице. Мы уже сделали это в файле app.js :

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

Это означает, что если мы добавим <head title="Homepage"> на домашнюю страницу нашего приложения с заголовком, это будет выглядеть так: <title>Home - My App</title> .

Мониторинг вашего приложения

Скорость является одним из наиболее важных факторов в оптимизации эффективности SEO на вашем сайте. По этой причине, если вы используете WordPress для своего веб-сайта, Kinsta APM поможет вам отслеживать и внимательно следить за вашим приложением в действии. Он помогает вам выявлять проблемы с производительностью WordPress и доступен бесплатно на всех сайтах, размещенных на Kinsta.

Резюме

Inertia.js — одна из самых значительных доступных технологий; смешайте его с Laravel, и вы получите современное одностраничное приложение, созданное с помощью PHP и JavaScript. Тейлор Отвелл, создатель Laravel, настолько заинтересован в Inertia, что Laravel выпустила свои самые популярные стартовые наборы, Laravel Breeze и Jetstream, с поддержкой Inertia и SSR.
Узнайте, как приступить к работе с Inertia.js и как использовать его с Laravel, Vue.js и Tailwind CSS для создания современного веб-приложения блога в этом руководстве. Нажмите, чтобы твитнуть
Если вы поклонник Laravel или профессиональный разработчик, Inertia.js, несомненно, привлечет ваше внимание. В этом уроке мы создали очень простой и понятный блог всего за несколько минут. Об инерции еще многое предстоит узнать, и это может быть только первая из многих статей и руководств.

Что еще в Laravel вы бы хотели, чтобы мы изучили? Дайте нам знать в комментариях ниже.