0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nuxt3のmiddleware実装をNuxt2と比較解説|AI実務ノート 編集部

Last updated at Posted at 2026-01-03

1. 結論(この記事で得られること)

この記事では、Nuxt3のmiddleware実装をNuxt2と比較しながら、実務で安全に移行・実装する方法をお伝えします。

具体的に得られること:

  • Nuxt2とNuxt3のmiddleware実装の違いとその理由
  • 型安全性を活かしたNuxt3らしい実装パターン
  • 既存コードの移行チェックリスト
  • AIを活用した問題切り分けと効率的なデバッグ手法
  • 実務で起こる失敗パターンとその対処法

私も初めてNuxt3のmiddlewareに触れたとき、「context」が消えて「え、「redirect」どうやるの?」と10分ぐらい固まった経験があります。この記事を読めば、そういう時間を節約できます。

2. 前提(環境・読者層)

想定環境:

  • Nuxt 3.x(3.10以降推奨)
  • TypeScript有効
  • Node.js 18以上

想定読者:

  • Nuxt2からの移行を検討している方
  • Nuxt3で認証・権限制御を実装する方
  • middleware周りでハマって困っている方

この記事で扱わないこと:

  • Nuxt2の基本的な使い方
  • Vue3の基礎文法

3. Before:よくあるつまずきポイント

3-1. Nuxt2のmiddleware(従来の書き方)

Nuxt2では「context」オブジェクトに全てが詰まっていました。

// middleware/auth.js (Nuxt2)
export default function ({ store, redirect, route }) {
  if (!store.state.user.loggedIn) {
    return redirect('/login?redirect=' + route.path)
  }
}
// nuxt.config.js (Nuxt2)
export default {
  router: {
    middleware: ['auth']
  }
}

Nuxt2の特徴:

  • 「context」から必要なものを分割代入
  • 「redirect」はcontext内の関数
  • グローバル指定は「nuxt.config.js」

3-2. Nuxt3で同じコードを書くと起こる問題

// ❌ これはNuxt3で動かない
export default function ({ store, redirect, route }) {
  // Error: context is undefined
}

よくあるエラーメッセージ:

  • 「navigateTo is not defined」
  • 「useRouter is not a function in middleware」
  • 「Cannot read properties of undefined (reading 'path')」

私が最初にハマったのは「グローバルmiddlewareの指定場所が分からない」でした。「nuxt.config.ts」を探し回ったんですが、実はファイル名規約で解決する仕様になっていたんです。

3-3. なぜ変わったのか(設計思想の違い)

Nuxt3では以下の思想で再設計されています:

コンテキスト
 Nuxt2: 巨大なcontextオブジェクト
 Nuxt3: Composables (useRouter等)

型安全性
 Nuxt2: 弱い(JSベース)
 Nuxt3: 強い(TS first)

実行順序
 Nuxt2: 曖昧
 Nuxt3: 明確(ファイル名・定義順)

SSR/CSR
 Nuxt2: 混在して分かりづらい
 Nuxt3: 明示的に分離可能

この変更は「巨大なcontextに何でも詰め込む設計からの脱却」です。実際、レビューでNuxt2のmiddlewareを見ると「これ何に依存してるか分からん」ってなりがちでした。

4. After:基本的な解決パターン

4-1. Nuxt3の基本構文

// middleware/auth.ts (Nuxt3)
export default defineNuxtRouteMiddleware((to, from) => {
  const user = useState('user')
 
  if (!user.value?.loggedIn) {
    return navigateTo({
      path: '/login',
      query: { redirect: to.path }
    })
  }
})

重要な変更点:

  • 「defineNuxtRouteMiddleware」でラップ
  • 引数は「(to, from)」 - Vue Routerと同じ
  • 「navigateTo」はグローバルに利用可能
  • 「useState」で状態を取得

4-2. グローバルmiddlewareの指定方法

// middleware/auth.global.ts
// ↑ ファイル名に `.global.ts` をつけるだけ
export default defineNuxtRouteMiddleware((to, from) => {
  // 全ページで実行される
})

4-3. ページ単位での指定

<!-- pages/dashboard.vue -->
<script setup lang="ts">
definePageMeta({
  middleware: ['auth', 'role-check']
})
</script>

4-4. 条件分岐とリダイレクト

// middleware/role-check.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const user = useState<User>('user')
 
  // 特定のパスでのみ実行
  if (to.path.startsWith('/admin')) {
    if (user.value?.role !== 'admin') {
      return navigateTo('/forbidden')
    }
  }
 
  // 何も返さなければ通過
})

ポイント:

  • 「return」しなければ次に進む
  • 「navigateTo」の戻り値をそのまま「return」
  • 型推論が効くのでtypo防止になる
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?