🧿

【Laravel】ZiggyからWayfinderに移行した理由と手順

に公開
3

対象読者

  • Laravel + Inertia.js で Ziggy を使用している方
  • セキュリティとパフォーマンスを重視した開発をしたい方
  • 開発体験や AI コーディングの精度を向上させたい方

はじめに

2025年8月のアップデートで、Laravel Starter Kit (React/Vue版)で使われている Ziggy が Wayfinder へ移行されたことをご存知でしょうか?

自社で開発しているプロジェクトにも Ziggy を使用しているものがあり、Wayfinder への移行を検証していました。移行が困難だと判断した場合は Ziggy のままで運用していくことも考えましたが、結果的にスムーズに移行することができました。(Ziggy と Wayfinder は併用可能なため、大規模プロジェクトでも段階的に移行することもできます。)

この記事では、ZiggyWayfinder の違い、移行のメリット、移行手順について学んだことをまとめます。

Ziggy と Wayfinder の違い

どちらも Laravel のルート情報をフロントエンドで扱えるようにするパッケージですが、実装方法に違いがあります。

特徴 Ziggy Wayfinder
開発元 Tighten Laravel公式
成熟度 安定版 ベータ版
アプローチ 実行時HTML注入/ビルド時生成 ビルド時にTS関数生成
ルート露出 フィルタリング設定可能 明示的に定義したもののみ
バンドルサイズ ルート数に依存 必要なルートのみ
TypeScript対応 型生成コマンドあり ネイティブサポート

Wayfinder に移行するメリット

1. セキュリティの向上

Ziggy はデフォルトで全ルート情報をクライアントに送信します。以下は、Ziggy が生成する HTML の一部です。

<script type="text/javascript">
const Ziggy={
  "url":"https://example.com",
  "routes":{
    "sanctum.csrf-cookie":{"uri":"sanctum/csrf-cookie","methods":["GET","HEAD"]},
    "admin.users.index":{"uri":"admin/users","methods":["GET","HEAD"]},
    "api.settings.update":{"uri":"api/settings/{id}","methods":["PUT","PATCH"],...},
    "dashboard":{"uri":"dashboard","methods":["GET","HEAD"]},
    // ... ルート定義が続く
  }
};
</script>

Ziggy が生成するスクリプトには、管理画面のパス(admin.users.index)や API エンドポイント(api.settings.update)など、ユーザーに知らせる必要のない情報が含まれています。

Wayfinder ではデフォルトで必要な情報のみを提供するため、不要なルート情報の露出を防ぎやすくなります。

2. パフォーマンスの向上

Ziggy はデフォルトで全ルート情報を HTML に出力する仕組みです。ルート数が多い大規模プロジェクトでは、Ziggy がレスポンスサイズを大きく増加させてしまいます。

Wayfinder はビルド時に必要なルート情報のみをバンドルします。ブラウザキャッシュが効くため再読み込みが速くなりますし、rel="modulepreload" が使われるようになっているので他のリソースと並行して読み込まれることでさらにパフォーマンスが向上します。

- <!-- 大量の Ziggy ルーティング定義 -->
- <script type="text/javascript">const Ziggy = {...}</script>

+ <!-- Ziggy 削除、代わりに必要最小限のアセットのみ -->
+ <link rel="modulepreload" as="script" href="/build/assets/app-XXXXXXXX.js" />
+ <script type="module" src="/build/assets/app-XXXXXXXX.js"></script>

私が移行したプロジェクト(ルート数135個)では、ログイン画面でのサンプリングで以下のような結果が得られました。

  • Before サイズ:53,716 bytes
  • After サイズ:8,341 bytes
  • 削減量:45,375 bytes(約84.5%の削減)

3. 開発体験の向上

Wayfinder は TypeScript の型定義をネイティブにサポートしており、ビルドプロセスに統合されているため、開発体験が向上します。

TypeScript の型定義により、エディターでルート名の自動補完やパラメータの型チェックが効くようになります。ルート削除時の影響箇所も把握しやすくなるため、リファクタリングも安全に行えます。

また、LSP (Language Server Protocol) を通じて Serena がこの情報を活用できるため、より正確なAIコーディング支援を期待できます。

移行手順

移行ガイドのドキュメントが見つけられなかったので、React Starter Kit の変更ログ を参考にしながら進めました。Vue の場合は、Vue Starter Kit の変更ログ を参考にしてください。

1. Wayfinder のインストール

まず、Wayfinder パッケージをインストールします。

composer require laravel/wayfinder
npm install -D @laravel/vite-plugin-wayfinder

2. Vite の設定

vite.config.ts に Wayfinder プラグインを追加します。

vite.config.ts
import { defineConfig } from 'vite'
import laravel from 'laravel-vite-plugin'
import react from '@vitejs/plugin-react'
+ import { wayfinder } from '@laravel/vite-plugin-wayfinder'

export default defineConfig({
  plugins: [
    laravel({
      input: ['resources/css/app.css', 'resources/js/app.tsx'],
      refresh: true,
    }),
    react(),
+   wayfinder({ formVariants: true }),
  ],
})

Vite の設定を追加したら、ルート定義を生成します。

php artisan wayfinder:generate

このコマンドにより、resources/js/routes ディレクトリにルート定義ファイルが生成されます。次回以降は、Vite の開発サーバー起動時やビルド時に自動的に更新されます。

3. .gitignore の更新

Wayfinder が生成するファイルを .gitignore に追加します。

.gitignore
+ /resources/js/actions
+ /resources/js/routes
+ /resources/js/wayfinder

4. フロントエンドコードの書き換え

プロジェクト内の全てのファイルで、Ziggy の route() 関数を Wayfinder のルート関数に置き換えていきます。

import { router } from '@inertiajs/react'
- import route from 'ziggy-js'
+ import { dashboard } from '@/routes'
+ import { show as showPost, store as storePost } from '@/routes/posts'

// 通常のルート
- router.visit(route('dashboard'))
+ router.visit(dashboard().url)

// パラメータ付きルート
- router.visit(route('posts.show', { id: 1 }))
+ router.visit(showPost({ id: 1 }).url)

// APIリクエストのルート
- axios.post(route('posts.store'), data)
+ axios.post(storePost().url, data)

5. Ziggy の削除

全てのコードを書き換えた後、Ziggy パッケージとバックエンドの設定を削除します。

パッケージの削除

composer remove tightenco/ziggy
npm uninstall ziggy-js

バックエンドの設定変更

app/Http/Middleware/HandleInertiaRequests.php から Ziggy のコードを削除します。

HandleInertiaRequests.php
use Illuminate\Http\Request;
use Inertia\Middleware;
- use Tighten\Ziggy\Ziggy;

class HandleInertiaRequests extends Middleware
{
    public function share(Request $request): array
    {
        return [
            ...parent::share($request),
            'auth' => [
                'user' => $request->user(),
            ],
-           'ziggy' => fn (): array => [
-               ...(new Ziggy)->toArray(),
-               'location' => $request->url(),
-           ],
        ];
    }
}

resources/views/app.blade.php の Ziggy のスクリプトタグも削除します。

app.blade.php
- @routes

Vue の場合は、resources/js/app.ts も修正が必要です。

app.ts
import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/vue3'
- import { ZiggyVue } from 'ziggy-js'

createInertiaApp({
  resolve: (name) => resolvePageComponent(`./pages/${name}.vue`, import.meta.glob<DefineComponent>('./pages/**/*.vue')),
  setup({ el, App, props, plugin }) {
    createApp({ render: () => h(App, props) })
      .use(plugin)
-     .use(ZiggyVue)
      .mount(el)
  },
})

プロジェクトに Ziggy 関連の型定義(resources/js/types/global.d.ts など)が存在する場合は、削除してください。

6. ビルドと確認

npm run build

TypeScript の型エラーなくビルドが成功し、全てのルーティングが正しく機能することを確認できれば移行完了です。

おわりに

Ziggy から Wayfinder への移行は、セキュリティ、パフォーマンス、型安全性の観点でメリットがあります。また、移行作業自体も比較的シンプルで、私の場合はあまり時間をかけずに移行することができました。

Wayfinder はまだベータ版なのですが、Laravel 公式でサポートされているため今後の標準になっていくと考えられます。冒頭でお伝えしたように Ziggy と Wayfinder は併用可能なので、大規模プロジェクトでも段階的に移行することができます。早期に移行しておくことで、将来的な移行コストを抑えられるかもしれません。ぜひ興味があれば試してみてください!

AUN Tech Blog

Discussion

NatsukiNatsuki

Ziggyのデメリットとして挙がっていたセキュリティ面とパフォーマンスの懸念には、@routesディレクトリでのフィルタリング、もしくはディレクティブの使用をやめてWayfinderのようにビルドを行うことで対応できるかなと思いましたが、何か懸念があったりしますでしょうか?
https://github.com/tighten/ziggy?tab=readme-ov-file#filtering-with-groups
https://github.com/tighten/ziggy?tab=readme-ov-file#re-generating-the-routes-file-when-your-app-routes-change

また、TypeScriptのサポートに関してもZiggyは直接にサポートされていて、ziggy:generate--typesもしくは--types-onlyで型補完のためのtsファイルが生成されます。(厳格な型チェックを行いたければたしかに.d.tsファイルに追記が必要なので、そのことを指して「手動設定」と表現しているのであれば、おっしゃる通りです。)
https://github.com/tighten/ziggy?tab=readme-ov-file#strict-route-name-type-checking

吉岡裕貴吉岡裕貴

コメントありがとうございます!フィードバックめちゃくちゃ嬉しいです。

ご指摘の通り、Ziggy でもフィルタリングやビルド時生成で対応可能ですね。また、TSサポートについても説明が不十分でした。表現が誤解を与えかねない内容になっていたので、近日中に修正したいと思います!

私が Wayfinder の記事を書いたのは、デフォルトで最適化されている点と、Laravel 公式として今後の標準になりそうな点を、みなさんにお知らせ・共有したかったからです。

貴重なご指摘、ありがとうございました!