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のplugin配置ルール変更の背景と対応方法|AI実務ノート 編集部

Last updated at Posted at 2026-01-03

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

Nuxt3では、Nuxt2から plugin の配置ルールと実行順序が大きく変わりました。この記事では以下を習得できます:

  • Nuxt2との差分を正確に理解し、既存資産を安全に移行する方法
  • 「.server」/「.client」 接尾辞の正しい使い分けと、SSR/CSRでのplugin分離設計
  • 実行順序を保証する命名規則(番号プレフィックス)の実務パターン
  • AI を活用した問題切り分けで半日かかる調査を30分に短縮する手法
  • 型安全に provide/inject を運用するTypeScript設計とテスト戦略

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

想定環境:

  • Nuxt 3.x(執筆時点 3.10以降を推奨)
  • Node.js 18.x 以上
  • TypeScript での開発を想定(JS の場合も応用可能)

想定読者:

  • Nuxt2 経験者で Nuxt3 への移行を検討している方
  • plugin の実行タイミングや順序で困った経験のある方
  • チーム開発で plugin 設計の標準化が必要な方

事前知識:

  • Nuxt の基本的なディレクトリ構造(「pages/」, 「composables/」 など)
  • Vue3 の Composition API と provide/inject の基礎
  • SSR/CSR の違いを概念的に理解している

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

3-1. Nuxt2 の書き方がそのまま動かない

Nuxt2 では 「nuxt.config.js」 に以下のように記述していました:

// Nuxt2 での記述(Nuxt3では動かない)
export default {
  plugins: [
    '~/plugins/axios',
    { src: '~/plugins/ga', mode: 'client' },
  ]
}

Nuxt3 では 「plugins/」 ディレクトリに配置するだけで自動登録されるため、config への記述は不要です。しかし、この仕様変更を知らずに config に書いてしまい「plugin が二重実行される」トラブルに遭遇するケースが頻発します。

3-2. 実行順序が保証されない

Nuxt3 では plugin はアルファベット順に実行されますが、暗黙的な依存関係がある場合に問題が起きます:

plugins/
  auth.ts         // 認証初期化(先に実行したい)
  api-client.ts   // 認証トークンを前提とするAPI client

この配置だと 「api-client.ts」 が先に実行され、認証情報がない状態で初期化されてしまいます。昔の私はこれで「開発環境では動くのに本番で 401 エラー」という地獄を味わいました。

3-3. SSR/CSR の分離が曖昧

Nuxt2 の 「mode: 'client'」 が通用せず、以下のような問題が起きます:

// window オブジェクトを使うコード(SSRで実行されるとエラー)
export default defineNuxtPlugin(() => {
  const tracker = new window.analytics.Tracker() // ReferenceError: window is not defined
})

「ローカルでは動くのにデプロイしたら500エラー」という典型的な SSR トラブルです。

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

4-1. ファイル名接尾辞で実行環境を制御

Nuxt3 では ファイル名の接尾辞で SSR/CSR を分離します:

plugins/
  01.auth.ts                    // SSR/CSR 両方で実行
  02.api-client.ts              // 両方で実行
  03.analytics.client.ts        // クライアントのみ
  04.prerender-meta.server.ts   // サーバーのみ

命名規則:

  • 「.client.ts」 → ブラウザのみで実行
  • 「.server.ts」 → サーバー(SSR/SSG)のみで実行
  • 接尾辞なし → 両方で実行

4-2. 番号プレフィックスで実行順序を保証

// plugins/01.auth.ts
export default defineNuxtPlugin(() => {
  const authToken = useCookie('auth_token')
 
  return {
    provide: {
      auth: {
        token: authToken.value,
        isAuthenticated: !!authToken.value
      }
    }
  }
})
 
// plugins/02.api-client.ts
export default defineNuxtPlugin((nuxtApp) => {
  const auth = nuxtApp.$auth // 01.auth.ts で provide された値を利用
 
  const api = $fetch.create({
    baseURL: '/api',
    headers: {
      Authorization: auth.token ? `Bearer ${auth.token}` : ''
    }
  })
 
  return {
    provide: { api }
  }
})

ポイント:

  • 「01」, 「02」 のように2桁の番号をプレフィックスとして付与(9個以上になっても順序が崩れない)
  • 依存関係が明確になり、コードレビューでも意図が伝わる

4-3. TypeScript 型定義の追加

// types/nuxt.d.ts
declare module '#app' {
  interface NuxtApp {
    $auth: {
      token: string | null
      isAuthenticated: boolean
    }
    $api: typeof $fetch
  }
}
 
declare module 'vue' {
  interface ComponentCustomProperties {
    $auth: {
      token: string | null
      isAuthenticated: boolean
    }
    $api: typeof $fetch
  }
}
 
export {}

これで 「nuxtApp.$auth」 や template 内の 「$auth」 が型安全になります。

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?