裝完 Laravel 後,我們就要開開心心地開始開發啦!首先第一步就是熟悉的 Laravel Router,把預設的 Welcome
視圖換成 Inertia 的視圖 HelloWorld
:
routes/web.php
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::get('/', function () {
return Inertia::render('HelloWorld');
});
PHP 7.4 後可以用 Arrow Functions (箭頭函數),原本 3 行程式碼變 1 行。如果你偏好喜歡 Helper functions 也可以使用:
Route::get('/', fn () => Inertia::render('HelloWorld'));
// 或
Route::get('/', fn () => inertia('HelloWorld'));
還是嫌太長?沒關係,Laravel 可以定義直接輸出視圖的路由 Route::view()
,Inertia 自然也可以:
Route::inertia('/', 'HelloWorld');
現在來建立頁面資料夾 resources/js/Pages
和對應的 Vue 頁面 HelloWorld.vue
:
前面
app.js
裡有用import(`@/Pages/${name}`)
動態引入 (Dynamic import),編譯時 Webpack 會先把Pages
資料夾下所有頁面包好,在瀏覽器執行時根據傳入的頁面名稱 (HelloWorld
) 渲染對應的頁面。
resources/js/Pages/HelloWorld.vue
<template>
<h1>Hello world</h1>
</template>
<script>
export default {
metaInfo: {
title: 'Page 1'
}
}
</script>
然後編譯前端資源:
yarn watch
開瀏覽器看一下結果:
看起來...沒什麼 SPA 的感覺,再加一個頁面還有導覽連結好了:
routes/web.php
Route::inertia('about', 'About');
resources/js/Pages/HelloWorld.vue
<template>
<div>
<div>
<inertia-link href="/">Hello world</inertia-link>
<inertia-link href="/about">About</inertia-link>
</div>
<h1>Hello world</h1>
</div>
</template>
<script>
export default {
metaInfo: {
title: 'Hello world'
}
}
</script>
resources/js/Pages/About.vue
<template>
<div>
<div>
<inertia-link href="/">Hello world</inertia-link>
<inertia-link href="/about">About</inertia-link>
</div>
<h1>About</h1>
</div>
</template>
<script>
export default {
metaInfo: {
title: 'About'
}
}
</script>
點擊 <inertia-link>
組件來切換頁面,不會重新整理頁面,他會在背後送出 Inertia 請求
後自動切換頁面 (Vue 組件)。宛如 SPA 應用般...不對!這就是 SPA 應用:
打開瀏覽器的 DevTools 檢查會發現,後端會回傳 Inertia Page 物件 給前端。
當然後端一定也要可以傳資料給前端,跟 Laravel 原本的用法一樣,傳個陣列過去就可以了:
routes/web.php
Route::get('/', fn () => Inertia::render('HelloWorld', [
'name' => 'Lucas',
]));
// 或
Route::inertia('/', 'HelloWorld', [
'name' => 'Lucas',
]);
Vue 組件可以用 props
接收:
resources/js/Pages/HelloWorld.vue
<template>
<div>
...
<h1>Hello {{ name }}</h1>
</div>
</template>
<script>
export default {
...
props: {
name: String
}
}
</script>
看!Inertia.js 開發 SPA 就是如此舒服!
Inertia 資產版本可以讓前端資源更新後,前端切換頁面時自動重新整理頁面,載入新的前端資源。原理很簡單,如果在後端有設定資產版本,Inertia Page 物件就會包含資產版本,發送 Inertia 請求時也會一併帶上 X-Inertia-Version
Header。如果前端發送請求時,後端檢測到資產版本已經更新,便會回傳一個 409 響應,通知前端需要強制重新整理頁面:
請求:
GET: http://example.com/events/80
Accept: text/html, application/xhtml+xml
X-Requested-With: XMLHttpRequest
X-Inertia: true
X-Inertia-Version: 6b16b94d7c51cbe5b1fa42aac98241d5
響應:
409: Conflict
X-Inertia-Location: http://example.com/events/80
在 Laravel Mix 要產生資產版本很簡單,有開啟 Laravel Mix 的 Version 功能後,mix-manifest.json
每次更新都會紀錄每個資源檔產生的 Hash 值,因此只要把 mix-manifest.json
丟給 PHP 的 md5_file()
函數產生 MD5 散列值,資產版本就出來了:
app/Providers/AppServiceProvider.php
use Inertia\Inertia;
public function register()
{
Inertia::version(fn () => md5_file(public_path('mix-manifest.json')));
}
然後到 HelloWorld.vue
隨便加幾個字,回到瀏覽器點 <inertia-link>
切換頁面,就會強制重新整理。
在完整的 SPA 中最常見的 Debug 方式,就是開瀏覽器 DevTools 的 Network 裡查 API 響應的結果,Debug 很不舒服。在 Inertia 如果有錯誤時會包裝在一個視窗內,而且還有原本後端提供漂亮的 Debug 介面。我們先回傳一個不存在的變數:
routes/web.php
Route::get('about', fn () => $fail);
然後從首頁點連結切換到 About 頁面:
看到沒?可以用 Laravel 漂亮的 Debug 頁面,果然還是習慣的最爽。但在線上環境 (production) 就不能暴露這些 Debug 資訊,現在來自訂 Inertia 專用的錯誤頁面:
app/Exceptions/Handler.php
use Illuminate\Support\Facades\App;
use Inertia\Inertia;
use Throwable;
public function render($request, Throwable $exception)
{
$response = parent::render($request, $exception);
$status = $response->getStatusCode();
$errorCodes = [
401 => 'Unauthorized',
403 => $exception->getMessage() ?: 'Forbidden',
404 => 'Not Found',
419 => 'Page Expired',
429 => 'Too Many Requests',
500 => 'Server Error',
503 => $exception->getMessage() ?: 'Service Unavailable',
];
if (App::environment('production')
&& in_array($status, array_keys($errorCodes))) {
return Inertia::render('Error', [
'code' => $status,
'message' => __($errorCodes[$status]),
])
->toResponse($request)
->setStatusCode($status);
}
return $response;
}
這段是判斷應用是不是在線上環境,和錯誤的 HTTP 狀態碼是不是上面其中之一,若皆是就回傳自訂的錯誤頁面。
resources/js/Pages/Error.vue
<template>
<div>
<div>{{ code }}</div>
<div>{{ message }}</div>
</div>
</template>
<script>
export default {
metaInfo() {
return {
title: this.message
}
},
props: {
code: Number,
message: String
}
}
</script>
然後把 APP_ENV
暫時改成 production
和開啟剛才的 $fail
頁面,來看看自訂的錯誤頁面:
搞定!(別忘了把 APP_ENV
改回 local
)
最後記得瀏覽器要安裝 Vue.js devtools,因為前端依然還是用 Vue.js 開發,devtools 的使用方式依然不變,而且有優秀的 Debug 工具才能加速解決問題。
見識到了極度舒適的 SPA 開發流程後,下一步就是要讓頁面變漂亮啦!Tailwind CSS 登場!顛覆你以前使用 CSS 的方式!
Lightning 範例程式碼:https://github.com/ycs77/lightning
你好
照著 Day3 做到這邊就被error卡住了
我的 npm 安裝的內容
npm install vue@^2.6 vue-meta@^2.4 vue-template-compiler@^2.6.12 @inertiajs/inertia@~0.6.1 @inertiajs/inertia-vue@~0.4.1
想請問如附圖的error如何排除,或有可能的排除方向
或是還需要什麼資訊
還請指教
謝謝!
請問有安裝 Laravel 端的 Inertia 套件嗎?
上面的 error 是跟 PHP 有關的喔!
composer require inertiajs/inertia-laravel
上面的 error 解決了,是安裝 Laravel 端的 Inertia 套件後我少了 Kernal.php 的設定。謝謝!
哈!不好一思,新版的套件有改,我馬上更新!
不會啦,因為,Inertia真的很新,剛好你分享了做法,讓我可以摸索一下方向
在 inertiajs/inertia-laravel
的 v0.3 之後有重大更新(不會自動註冊 Middleware),剛才想了想,我決定不更新,如果你要跟著這個系列做的話,建議還是安裝 ^0.2 版的。用新版的話需要自行看過官方文檔。
composer require inertiajs/inertia-laravel:^0.2
好的,謝謝!
或 v3.0 之後的 release:https://github.com/inertiajs/inertia-laravel/releases
請問,接著出現附圖的 error
這要朝哪個方向排除
謝謝!
ps 補問一下,前幾天試著做 splik chunk 的時候,也出現了類似的問題,只要網址後被加上亂數,就會 404,後來我只好先拿掉 webpack,單純用 laravel mix 的 extract,但是 extract 只是讓 app.js 變小,讓 vender.js 變大。想請問這是不是哪邊少了設定,謝謝!
css/app.css
/js/app.js
不存在,看看 public 資料夾下面有沒有webpack.mix.js
設定不行嗎?