Nuxt3のmiddlewareの登録と呼び出し&Beta版のバグとその回避策
  • 2022.03.14に公開
  • Nuxt3
  • 0. Nuxt3
  • No.5 / 9
現在このカテゴリーは、Nuxt3パブリックベータ版の情報を公開しています。変更の可能性が大きくあるので、最新の情報は Nuxt3の公式サイト をご確認ください。

middlewareとは?

middlewareとは、特定のルートに移動するに何らかの処理を実行したい場合に使用するNuxtの機能です。

例えば、認証前のユーザーをリダイレクトさせたい場合などに使用します。

Nuxt3では2つの方法でmiddlewareを定義できます。

1. middlewareディレクトリを使用する

「middleware」ディレクトリ以下に、処理を実行するts ファイルを置くことでミドルウェアを登録することができます。

ディレクトリとミドルウェアファイルの作成
% mkdir middleware && touch $_/auth.ts

middlewareの登録

ミドルウェアを登録するには、defineNuxtRouteMiddlewareを使用します。

引数には2つの値が取れます。

  1. to ... ページ遷移のルート情報
  2. from ... ページ遷移のルート情報
middleware/auth.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
  console.log('middleware/auth')
  console.log('to', to)
  console.log('from', from)
})

第三引数のnextは取得できません。

vue-router docsのナビゲーションガードとは異なり、3番目のnext()引数は渡されず、リダイレクトまたはルートキャンセルは、ミドルウェアから値を返すことによって処理されます。

引用: Nuxt 3 - Meddleware directory

middlewareの呼び出し

呼び出しにはページファイルdefinePageMetaを使用します。

Nuxt3ではレイアウトファイルからのミドルウェアの呼び出しはできません。

pages/index.vue
<script setup lang="ts">
  definePageMeta({
    middleware: ['auth']
  })
</script>

/testから/に移動した際のログは以下の通りです。

console
middleware/auth
to {fullPath: '/', path: '/', query: {…}, hash: '', name: 'index', …}
from {fullPath: '/test', path: '/test', query: {…}, hash: '', name: 'test', …}

ページ遷移がサーバーを経由する場合、サーバ側でもミドルウェアが呼び出されます。

terminal

2022-03-14 09-14-55

2. addRouteMiddlewareを使用する

ミドルウェアを動的に追加するaddRouteMiddlewareを使用すれば、「plugins」ディレクトリ内でも定義できます。

ディレクトリとプラグインファイルの作成
% mkdir plugins && touch $_/middleware.ts

プラグインファイルはNuxt2と同じくnuxt.config.tsに登録します。

nuxt.config.ts
import { defineNuxtConfig } from 'nuxt3'

export default defineNuxtConfig({
  plugins: [
    '~/plugins/middleware'
  ]
})

pluginの登録

Nuxt3のプラグインにはdefineNuxtPluginを使用します。

渡される引数は、Nuxt3のインスタンスであるnuxtAppのみです。

参考: Nuxt 3 - Plugins directory

plugins/middleware.ts
export default defineNuxtPlugin((nuxtApp) => {
})

middlewareの登録

ミドルウェアを登録するには、addRouteMiddlewareを使用します。

  • addRouteMiddleware('key', function())

    • 第一引数 ... 任意のキー(呼出名)。

    • 第二引数 ... 実行したい処理。

plugins/middleware.ts
export default defineNuxtPlugin((nuxtApp) => {
  addRouteMiddleware('local-middleware', () => {
    console.log('plugins/middleware/local')
    console.log('nuxtApp', nuxtApp)
  })
})

middlewareの呼び出し

addRouteMiddlewareで登録したミドルウェアも呼び出し方法は同じです。

pages/index.vue
<script setup lang="ts">
  definePageMeta({
    middleware: ['local-middleware']
  })
</script>
console
plugins/middleware/local
nuxtApp {globalName: 'nuxt', payload: Proxy, isHydrating: true, _asyncDataPromises: {…}, provide: ƒ, …}

addRouteMiddlewareのタイプエラー回避

addRouteMiddlewareを使用する方法は、型チェックを行うVolarがエラーを吐きます。

2022-03-14 09-53-24

type MiddlewareKeyは「middleware」ディレクトリにファイルを作成すると自動で値が追加されます。

その実態は.nuxt/types/middleware.d.tsで参照できます。

.nuxt/types/middleware.d.ts
import type { NavigationGuard } from 'vue-router'
export type MiddlewareKey = "auth"
declare module "/<Project path>/node_modules/nuxt3/dist/pages/runtime/composables" {
  interface PageMeta {
    middleware?: MiddlewareKey | NavigationGuard | Array<MiddlewareKey | NavigationGuard>
  }
}

addRouteMiddlewareで追加したmiddlewaretype MiddlewareKeyに名前が追加されません。

回避策としてTypeScriptのasを使用し、型を上書きします。

pages/index.vue
<script setup lang="ts">
  /** 
   * MiddlewareKey type error 回避策
   * addRouteMiddleware()で追加したmiddlewareキーを手動で追加する
   * Nuxt version 3.0.0-27444434.856c01a
  */
  import { MiddlewareKey } from '~/.nuxt/types/middleware'
  type AddRouteMiddleware = MiddlewareKey & 'local-middleware'

  definePageMeta({
    middleware: ['local-middleware'] as Array<AddRouteMiddleware>
  })
</script>

Nuxt3のグローバルミドルウェア

全てのルートで実行したい処理がある場合は、グローバルミドルウェアを使用します。

1. middlewareディレクトリを使用する

「middleware」ディレクトリ以下に作成する場合は、.globalがついたミドルウェアファイルを作成します。

グローバルミドルウェアの作成
% touch middleware/auth.global.ts
middleware/auth.global.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
  console.log('middleware/auth.global')
})

.globalのファイルは呼び出し作業は不要です。

どのルートに遷移しても下記のコンソールが出力されます。

console
middleware/auth.global

2. addRouteMiddlewareを使用する

addRouteMiddlewareを使用してグローバルミドルウェアを登録する場合、{ global: true }オプションを渡します。

plugins/middleware.ts
export default defineNuxtPlugin((nuxtApp) => {
  addRouteMiddleware('global-middleware', () => {
    console.log('plugins/middleware/global')
  }, { global: true })
})

ただしこの方法、middlewareがなぜか2回呼ばれます。

Beta版のうちは使用しない方が良いかもしれません。

console

2022-03-14 12-01-57

下記はNuxt Version: 3.0.0-27444434.856c01a の状況です。

middlewareでリダイレクトを行うには、navigateTo('/')またはnavigateTo({ path: '/' })を使用します。

middleware/auth.global.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
  console.log('middleware/auth.global')
  // /testにリダイレクトするコード
  return navigateTo('/test')
})

グローバルミドルウェアのnavigateToはVue Routerが無限ループを引き起こします。

Detected an infinite redirection in a navigation guard when going from "/" to "/test".
Aborting to avoid a Stack Overflow. This will break in production if not fixed.
terminal

2022-03-14 12-08-40

これはaddRouteMiddlewareを使用しても結果は同じです。

現状のNuxt3では、グローバルミドルウェアでのリダイレクト処理は実行できません。

ローカルミドルウェアならnavigateToが使用可能

回避策として、ローカルミドルウェアにnavigateToを使用しリダイレクト処理を行います。

middleware/auth.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
  console.log('middleware/auth')
  return navigateTo('/test')
})

ただし、グローバルに使用する場合は全てのページにミドルウェアを登録する必要があります。

pages/index.vue
<script setup lang="ts">
  definePageMeta({
    middleware: ['auth']
  })
</script>

Nuxt3ではレイアウトファイルのmiddlewareが無くなったため八方塞がりの状況です。

今後の改善を待ちましょう。

Nuxt3beta middlewareまとめ

  • middlewareを登録する2つの方法
    1. 「middleware」ディレクトリ内のファイルで処理を記述する
    2. addRouteMiddlewareでミドルウェアを登録する
  • middlewareの呼出し
    • ページファイルのdefinePageMeta.middlewareから呼び出す
    • レイアウトファイルからの呼出不可
    • 【バグ?】addRouteMiddlewareで登録したミドルウェアのキーが追加されない
    • 【バグ回避】type MiddlewareKeyに手動でキーを追加する
  • グローバルミドルウェア
    • 「middleware」ディレクトリを使用する場合、ファイル名に.globalを付ける
    • addRouteMiddlewareを使用する場合、{ global: true }オプションを追加する
    • 【バグ?】リダイレクトを行うnavigateToはエラーとなり使用不可
    • 【バグ回避】リダイレクト処理はローカルミドルウェアを使用する
あなたの力になれること
私自身が独学でプログラミングを勉強してきたので、一人で学び続ける苦しみは痛いほど分かります。そこで、当時の私がこんなのあったら良いのにな、と思っていたサービスを立ち上げました。周りに質問できる人がいない、答えの調べ方が分からない、ここを聞きたいだけなのにスクールは高額すぎる。そんな方に向けた単発・短期間メンターサービスを行っています。
独学プログラマのサービス
独学プログラマ
独学でも、ここまでできるってよ。
CONTACT
Nuxt.js制作のご依頼は下記メールアドレスまでお送りください。