如何在你的 Laravel 項目中使用 Inertia.js

已發表: 2022-12-08

多頁應用程序 (MPA) 越來越不流行了。 Facebook、Twitter、YouTube、Github 等著名平台已經在使用單頁應用程序 (SPA) 技術。

這種流行的技術允許用戶快速響應地使用 Web 應用程序,因為一切都是客戶端呈現的。 但是,對於使用 Laravel 或 Django 等框架構建服務器端呈現應用程序的開發人員來說,這可能是一種痛苦。

幸運的是,Inertia.js 介入並進行了救援。
你的 Laravel 項目缺少的成分是什麼? 慣性.js。 在這份詳盡的指南中了解更多信息點擊推文
在本文中,我們將向您展示如何開始使用 Inertia.js 以及如何將其與 Laravel、Vue.js 和 Tailwind CSS 結合使用來創建現代博客 Web 應用程序。 我們還將分享如何使 SPA 對 SEO 更友好,以及一些其他技巧。

如果你剛剛開始使用 Laravel,我們建議你先閱讀這篇文章,這樣你就可以開始了。

為什麼選擇水療?

在我們問為什麼要使用 Inertia 之前,我們必須先問:“為什麼是 SPA?”

為什麼有人會比傳統的服務器端應用程序更喜歡客戶端呈現的應用程序? 什麼會迫使全棧 Laravel 開發人員告別刀片組件?

簡短的回答:因為速度和響應能力對於任何成功的用戶參與都是必不可少的。

對於 MPA,瀏覽器會不斷向後端發送請求,然後後端會執行大量數據庫查詢。 在數據庫和服務器處理查詢並將它們傳遞給瀏覽器之後,頁面就呈現出來了。

但是SPA不一樣。 該應用程序將用戶需要的所有內容直接帶到頁面,無需瀏覽器發送查詢或重新加載頁面以呈現新的 HTML 元素。

由於這種獨一無二的用戶體驗,許多知名公司都在呼籲將他們的網站變成單頁應用程序。

話雖如此,創建單頁應用程序對於 Laravel 開發人員來說可能很困難,因為這將要求他們開始使用 Vue.js 或 React 而不是 blade 模板,從而導致失去許多節省時間和精力的 Laravel gem。

不過,現在有了 Inertia.js,一切都變了。

為什麼是慣性?

如果 Laravel 開發人員要在 Inertia 之前使用 Vue 構建 web SPA,他們必須設置 API 並使用 Laravel 返回 JSON 數據,然後使用 AXIOS 之類的東西來檢索 Vue 組件中的數據。 他們還需要 Vue Router 之類的東西來管理路由,這將意味著失去 Laravel 路由,以及中間件和控制器。

另一方面,Inertia.js 使開發人員能夠使用經典的服務器端路由和控制器構建現代單頁 Vue、React 和 Svelte 應用程序。 Inertia 專為 Laravel、Ruby on Rails 和 Django 開發人員設計,允許他們在不更改創建控制器、從數據庫獲取數據和呈現視圖的編碼技術的情況下構建應用程序

感謝 Inertia.js,Laravel 開發人員將感到賓至如歸。

慣性如何運作

僅使用 Laravel 和 Vue 構建 SPA 將為您的前端提供完整的 JavaScript 頁面,但這不會為您提供單頁面應用程序體驗。 每個單擊的鏈接都會導致您的客戶端框架在下一個頁面加載時重新啟動。

這就是慣性發揮作用的地方。

Inertia 基本上是一個客戶端路由庫。 它允許您在頁面之間導航而無需重新加載整個頁面。 這是通過<Link>組件實現的,它是一個圍繞標準錨標記的輕量級包裝器。

當您單擊 Inertia 鏈接時,Inertia 會攔截單擊並將您重定向到 XHR。 瀏覽器不會以這種方式重新加載頁面,從而為用戶提供完整的單頁體驗。

慣性入門

一個簡單的頁面,頂部帶有藍色橫幅中的“Kinsta 博客”和一行示例文章卡片。
使用 Inertia.js 製作的示例頁面

為了了解 Inertia 以及如何將它與 Laravel 集成,我們將使用最強大的組合構建一個名為Kinsta Blog的博客 Web 應用程序,Laravel 用於後端,Vue.js 用於 JavaScript 前端,Tailwind CSS 用於樣式。

如果您更喜歡在本地環境中學習本教程,您可以使用 DevKinsta,它是開發人員、設計人員和代理機構的強大工具,使他們能夠構建單頁和多頁 WordPress Web 應用程序。 幸運的是,使用 Corcel 包可以輕鬆地將 WordPress 與 Laravel 集成。

先決條件

要充分利用本教程,您應該熟悉以下內容:

  • Laravel 基礎知識(安裝、數據庫、數據庫遷移、Eloquent 模型、控制器和路由)
  • Vue.js 基礎知識(安裝、結構和表單)

如果您不確定,請查看這些精彩的 Laravel 免費和付費教程。 否則,讓我們開始吧。

第一步:安裝核心元素

要專注於 Inertia.js 並立即進入有趣的部分,請確保您已準備好以下設置:

  1. 新安裝的名為kinsta-blog的 Laravel 9 項目
  2. 在我們的 Laravel 項目中安裝了 Tailwind CSS CLI
  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. 連接到我們項目的名為kinsta_blog的 MySQL 本地數據庫:

    .env ”:

     DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=kinsta_blog DB_USERNAME=root DB_PASSWORD=
  5. 文章模型、遷移和工廠:

    “app/Models/ Article.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.服務器端

我們需要做的第一件事是通過 Composer 使用以下終端命令安裝 Inertia 服務器端適配器。

 composer require inertiajs/inertia-laravel

現在我們將設置我們的根模板,它將是一個用於加載您的 CSS 和 JS 文件的刀片文件,以及一個將用於啟動我們的 JavaScript 應用程序的慣性根。

因為我們使用的是最新版本的 Laravel 9 v9.3.1,我們還必須通過將 Vite 包含在/resources/views/app.blade.php的標籤中來啟用 Vite 以發揮其魔力:

 <!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 知道我們創建應用程序和導入 CSS 的 JavaScript 主文件的路徑。 Vite 是一種有助於 JavaScript 和 CSS 開發的工具,它允許開發人員在本地開發期間無需刷新頁面即可查看前端更改。

我們的下一步是創建HandleInertiaRequests中間件並將其發佈到我們的項目中。 我們可以通過在項目的根目錄中觸發以下終端命令來做到這一點:

 php artisan inertia:middleware

完成後,前往“App/Http/ Kernel ”並將HandleInertiaRequests註冊為 Web 中間件中的最後一項:

 '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 文件以使用 Vue.js 3、Vite 和 Laravel 初始化 Inertia.js:

“資源/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

瞧! 您已經擁有一個使用 Vue.js 3 和 Vite 的 Laravel 9 應用程序。 現在我們需要看到實際發生的事情!

創建慣性頁面

您還記得用於查看我們的主頁和一篇文章的那兩個刀片文件( indexshow )嗎?

使用 Inertia 時我們唯一需要的刀片文件是app.blade.php ,我們在安裝 Inertia 時已經使用過一次。 那麼現在這些文件會怎樣呢?

我們會將這些文件從刀片組件轉換為 Inertia.js 組件。

應用程序中的每個頁面都有自己的控制器和帶有 Inertia 的 JavaScript 組件。 這使您可以僅獲取該頁面所需的數據,而無需使用 API。 慣性頁面只不過是 JavaScript 組件,在我們的例子中,它們是 Vue.js 組件。 他們沒有什麼特別值得注意的地方。 所以我們要做的是將所有 HTML 內容包裝在<template>標籤之間,任何與 JavaScript 相關的內容都將用<script>標籤包裝。

創建一個名為“Pages”的文件夾並將文件移到那裡。 所以我們將在“ ./resources/js/Pages ”中包含“ index.blade.php ”和“ show.blade.php ”。 然後我們將文件格式更改為“.vue”而不是“.blade.php”,同時將其名稱的首字母大寫並將其內容轉換​​為標準的 Vue.js 組件。 我們將排除<html><head><body>標籤,因為它們已經包含在主根刀片組件中。

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

有件事真的很困擾我! 我們一直在每個組件中復制和粘貼我們的頁眉和頁腳,這不是一個很好的做法。 讓我們創建一個 Inertia 基本佈局來存儲我們的持久化組件。

在“ /resources/js ”中創建一個名為“Layouts”的文件夾,並在該文件夾中創建一個名為“KinstaLayout.vue”的文件。 這個文件將包含我們的頁眉和頁腳以及帶有<slot />main文件,以允許用此佈局包裹的所有組件嵌入其中。 該文件應如下所示:

“資源/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>

然後我們將在我們的頁面中導入這個新佈局並用它包裝所有 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 路由和慣性渲染

首先讓我們使用我們從教程起點獲得的“ ArticleFactory ”文件,並將一些文章播種到我們的數據庫中。

數據庫/seeders/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 來渲染視圖,我們用來編寫路由的方式將略有改變。 讓我們在“routes/ web.php ”中創建我們的第一個 Laravel Inertia 路由,並從“ /resources/js/Pages/Index.vue ”返回主頁視圖。

“routes/ web.php ”:

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

請注意,我們導入了Inertia並且沒有使用view() Laravel 助手來返回視圖,而是使用了Inertia::render 。 默認情況下,Inertia 還會在“resources/js”的頁面文件夾中查找我們在路由中提到的文件名。

前往索引文件並將檢索到的數據設置為 prop 並使用v-for循環它們以顯示結果。 在腳本標籤之間,將傳遞的數據定義為道具。 Inertia 需要知道的只是您期望的數據類型,在我們的例子中是包含文章數組的“文章”對象。

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

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

請注意,僅將其定義為道具而不返回它就足夠了,因為我們使用的是 Vue.js 3 組合 API 的setup格式。 如果我們使用選項 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 擴展顯示打開頁面的慣性屬性列表。
檢查慣性屬性。

“文章”作為包含文章數組的道具對像傳遞給組件; 數組中的每篇文章也是一個對象,其屬性與它從數據庫中獲取的數據相對應。 這意味著我們從 Laravel 傳輸到 Inertia 的任何數據都將被視為道具。

在 Inertia.js 中使用 Tailwind CSS

由於 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: [], };

然後確保我們已經在“resources/js/ app.js ”中導入了我們的 CSS 文件:

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

現在我們準備好設計我們的組件了。

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

“資源/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>

如果你查看瀏覽器,你會注意到 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');

我們導入了“Article”模型並添加了一個新路由來返回Show.vue Inertia 組件。 我們還利用了 Laravel 的路由模型綁定,它允許 Laravel 自動獲取我們所指的文章。

我們現在需要的是一種通過單擊主頁上的鏈接而無需重新加載整個頁面來訪問此路由的方法。 這可以通過 Inertia 的神奇工具<Link>來實現。 我們在介紹中提到 Inertia 使用<Link>作為標準錨標記<a>的包裝器,並且該包裝器旨在使頁面訪問盡可能無縫。 在 Inertia 中, <Link>標籤可以充當執行<GET>請求的錨標籤,但它也可以同時充當<button><form> 。 讓我們看看如何將它應用到我們的項目中。

在我們的 Index.vue 中,我們將從 Inertia 導入<Link> ,並刪除錨標籤<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>

讓我們使用 Tailwind 為Show.vue設計樣式,讓它看起來更盛裝一點,為我們的訪問做好準備。 我們還需要讓它知道它應該期待一個“文章”對象並將其設置為道具:

 <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>進行POSTPUTPATCHDELETE

“routes/ web.php ”:

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

你應該知道的 Laravel Inertia 提示和技巧

我們現在有一個使用 Laravel、Inertia 和 Tailwind CSS 構建的工作 SPA。 但是慣性可以幫助我們取得更多成就。 是時候學習一些對開發人員和應用程序訪問者都有幫助的慣性技術了。

生成網址

您可能已經註意到我們一直在為我們的 Laravel 路由添加名稱而不使用它。 Inertia 允許我們在我們的組件中使用我們命名的路由,而不是手動寫下完整的路由。

我們可以通過在我們的項目中安裝 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 的包裝器,它根據慣性事件有條件地顯示加載指示器。 你真的不需要知道它在幕後是如何工作的,所以讓我們讓它工作吧。

我們可以使用以下終端命令安裝這個庫:

 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 博客”標題,右上角帶有旋轉指示器。
Inertia 進度指示器(右上角)。

滾動管理

在某些情況下,您可能希望在保持相同滾動位置的同時導航到新頁面。 如果您允許用戶發表評論,也許您會需要它; 這將提交一個表單並將新評論從數據庫加載到您的組件中; 您會希望在用戶丟失滾動位置的情況下發生這種情況。 慣性為我們解決了這個問題。

在我們的例子中,讓我們將其應用於Index.vue中的<Link>標籤。 要在使用 Inertia 的<Link>重定向到不同頁面時保留滾動位置,我們需要做的就是向<Link>添加preserve-scroll屬性:

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

搜索引擎優化技巧

自SPA誕生以來,人們就一直關注搜索引擎優化(SEO)。 眾所周知,如果您使用 SPA 方法,搜索引擎將很難抓取您的 Web 應用程序,因為所有內容都是客戶端呈現的,導致您的網站不會顯示在搜索結果的頂部; 儘管如此,為什麼像 Facebook 和 Github 這樣的流行平台現在是 SPA,並且在 SEO 中仍然表現良好?

嗯,這不是任務:不再是不可能的了。 Inertia 提供了一些解決方案來幫助您的 SPA 變得對 SEO 友好。

使用 Laravel 和 Vite 的慣性 Vue SSR

搜索引擎總是在您的網站上尋找 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

另一個有用的 Inertia“NPM”包提供了一個簡單的“HTTP”服務器。 強烈建議您安裝它:

 npm install @inertiajs/server

然後,在“resources/js/”中,我們將添加一個名為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 的創建者 Taylor Otwell 對 Inertia 如此感興趣,以至於 Laravel 推出了其最受歡迎的入門套件 Laravel Breeze 和 Jetstream,並支持 Inertia 和 SSR。
在本指南中了解如何開始使用 Inertia.js 以及如何將其與 Laravel、Vue.js 和 Tailwind CSS 一起使用以創建現代博客 Web 應用程序點擊推
如果您是 Laravel 粉絲或專業開發人員,Inertia.js 無疑會吸引您的眼球。 在本教程中,我們只用了幾分鐘就創建了一個非常基礎和直接的博客。 關於慣性還有很多東西需要學習,這可能只是眾多文章和教程中的第一篇。

關於 Laravel,您還希望我們探索什麼? 請在下面的評論部分告訴我們。