Nuxt 3 で middleware が初回ロードで動かない原因と修正方法

Nuxt 3 でアプリケーションを構築していると、ルートごとにアクセス制御や処理を挟むために middleware を利用することが多くあります。しかし「初回ロード時に middleware が走らない」「SSR では効かない」といった問題に直面するケースが開発者の間で報告されています。

本記事では、その原因と正しい middleware の使い方、そして初回ロードや SSR においても期待通り動作させるための実装方法を詳しく解説します。

1. Nuxt 3 middleware の基本仕様

Nuxt: The Progressive Web Framework
Create high-quality web applications with Nuxt, the open source framework that makes full-stack development with Vue.js ...

Nuxt 3 では defineNuxtRouteMiddleware を使ってカスタム middleware を定義します。これは Vue Router の beforeEach と似ていますが、Nuxt のルーティングシステムに統合されている点が異なります。通常、middleware はページ遷移ごとに呼ばれ、ルートの認証チェックやリダイレクト処理などを担います。

しかし SSR のタイミングでは「最初に描画されるページの middleware」が一見無視されたように見えることがあります。実際には動作していますが、仕組みを理解していないと見落としやすいポイントです。

2. 初回ロードで動かないように見える理由

初回アクセスでは SSR によりサーバーでレンダリングされた HTML が返り、クライアント側でハイドレーションされます。

このとき、middleware の実行は SSR と CSR の両方に関与するため、console.log などで確認すると「初回に走っていない」ように見えることがあります。実際にはサーバーサイドで処理されており、ブラウザの開発ツールでは見えないため誤解が生まれます。また、middleware の定義場所が正しくない場合(例: middleware ディレクトリに配置せずインポートしているなど)には、本当に初回実行されない状況も発生します。

3. 正しい定義と使い方

middleware は ~/middleware ディレクトリに配置し、defineNuxtRouteMiddleware を用いてエクスポートするのが基本です。以下は認証チェック用の例です。

// ~/middleware/auth.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const user = useState('user')
  if (!user.value && to.path !== '/login') {
    return navigateTo('/login')
  }
})

このように .global.ts として定義すると、すべてのルートで必ず実行されます。もし特定ページにのみ適用したい場合は .ts として置き、ページコンポーネントで definePageMeta を使って指定します。

<script setup lang="ts">
definePageMeta({
  middleware: 'auth'
})
</script>

このように記述すれば、auth.ts で定義した middleware がそのページにアクセスするときのみ実行されます。

4. SSR と CSR の挙動の違い

SSR では初回リクエストの段階で middleware がサーバー上で評価されます。したがって、サーバーログを確認すると確かに middleware が走っていることが分かります。一方、CSR によるページ遷移時にはクライアントで middleware が評価されます。つまり 同じ middleware が SSR と CSR の両方で動いているが、出力の見え方が異なる ため「初回に動かない」と誤解されやすいのです。

もし初回ロードでもブラウザで動作確認したいなら、サーバー側のログに出力するか、環境ごとに挙動を分けて調査するとよいでしょう。

SSR での確認例

export default defineNuxtRouteMiddleware((to, from) => {
  console.log('[SSR middleware]', to.fullPath)
})

これを仕込むことで、サーバー側コンソールにログが出力され、SSR タイミングでも確実に動作していることが確認できます。

5. 実務でのトラブルシューティング

実務では以下のような誤りが原因で「middleware が初回ロードで動かない」と勘違いされがちです。

  • middleware ファイルを ~/middleware ディレクトリ以外に置いている
  • .ts ファイル名に .global を付け忘れているため、全ページに適用されていない
  • SSR と CSR の挙動の違いを理解せず、ブラウザ側だけで動作確認している
  • defineNuxtRouteMiddleware を使わず、Vue Router のフックを直接使っている

これらを一つずつ確認していくことで、多くの問題は解消されます。また、Docker やクラウド環境にデプロイしている場合、環境変数やキャッシュ設定が影響して SSR の挙動が異なるように見えるケースもあるため、ローカルと本番での挙動を比較することも有効です。

6. 今後のベストプラクティス

今後 Nuxt 3 で middleware を正しく運用するには、以下のようなベストプラクティスを守るとよいでしょう。

  • 認証チェックなど全ページ共通の処理は .global.ts として定義
  • ページ固有の処理は definePageMeta で指定
  • SSR と CSR 双方でログを仕込み、初回ロード時の挙動をサーバー側でも確認
  • 開発時に誤解しないよう、console.log はサーバーとクライアントの両方で見る習慣をつける
  • 不具合を疑う前に middleware の配置・命名規則を再確認する

これらを徹底すれば、「初回ロードで middleware が動かない」という問題の多くは防げます。

まとめ

Nuxt 3 で middleware が初回ロード時に動かないように見えるのは、実際には SSR で処理されているためブラウザで確認できないことが原因です。また、定義場所や命名規則の誤りによって本当に動作しないケースもあります。正しい使い方を理解し、SSR と CSR の違いを意識することで、この問題は回避可能です。

参考

タイトルとURLをコピーしました