# Nuxt 4の新機能を徹底解説:ディレクトリ構造の刷新とNuxt 3からの移行ガイド(2026年版)
> Nuxt 4で導入されたapp/ディレクトリ構造、シングルトンデータフェッチ層、shallow reactivity、TypeScript分割コンテキストについて、コード例を交えて詳しく解説します。
- Published: 2026-05-01
- Updated: 2026-05-01
- Author: SharpSkill
- Tags: nuxt, vue, migration, typescript, tutorial
- Reading time: 8 min
---
Nuxt 4は、アプリケーションコードと設定ファイルを明確に分離する新しいディレクトリ構造を導入しました。2025年7月にリリースされ、2026年4月時点でバージョン4.4に到達したこのメジャーアップデートは、シングルトンデータフェッチ層、shallowReactivityのデフォルト化、TypeScriptコンテキストの分割など、開発体験を大幅に改善する機能を備えています。Nuxt 2からNuxt 3への移行と比較すると、今回のアップグレードパスは格段にスムーズです。
> **自動マイグレーションツール**
>
> NuxtチームはCodemodと連携し、ほとんどの移行ステップを自動化しています。`npx codemod@latest nuxt/4/migration-recipe` を実行すると、ディレクトリ再構築、データフェッチの更新、非推奨APIの置換が自動的に処理されます。
## Nuxt 4のapp/ディレクトリ構造
Nuxt 4では、すべてのアプリケーションソースコードがデフォルトで`app/`ディレクトリに配置されます。この変更は実際の開発上の課題を解決するものです。LinuxやWindowsのファイルウォッチャーは、アプリケーションコードが`node_modules/`や`.git/`、設定ファイルと混在せず、専用のサブディレクトリに格納されている場合、大幅にパフォーマンスが向上します。
新しいディレクトリレイアウトは以下の通りです。
```text
my-nuxt-app/
├─ app/
│ ├─ assets/
│ ├─ components/
│ ├─ composables/
│ ├─ layouts/
│ ├─ middleware/
│ ├─ pages/
│ ├─ plugins/
│ ├─ utils/
│ ├─ app.vue
│ ├─ app.config.ts
│ └─ error.vue
├─ content/
├─ public/
├─ shared/ # 新規:appとserver間で共有するコード
├─ server/
└─ nuxt.config.ts
```
`shared/`ディレクトリは特筆すべき追加要素です。`shared/`に配置されたcomposableやユーティリティは、VueアプリとNitroサーバーの両方で自動インポートされます。バリデーションスキーマ、型定義、ユーティリティ関数をコンテキスト間で共有する際に、手動のimport文を記述する必要がなくなります。
## Nuxt 3からNuxt 4へのステップバイステップ移行
アップグレードプロセスは1つのコマンドから始まります。Nuxtは既存のフラット構造を検出し、変更なしで動作を継続するため、段階的な移行が可能です。
```bash
# Nuxtのアップグレードと依存関係の重複解消
npx nuxt upgrade --dedupe
```
パッケージのアップグレード後、アプリケーションファイルを`app/`ディレクトリに移動します。
```bash
# ディレクトリ再構築の自動化
npx codemod@latest nuxt/4/file-structure
```
このcodemodにより、`assets/`、`components/`、`composables/`、`layouts/`、`middleware/`、`pages/`、`plugins/`、`utils/`、`app.vue`、`error.vue`、`app.config.ts`が`app/`に移動されます。ルートに残すべきファイル(`nuxt.config.ts`、`server/`、`public/`、`content/`)はそのまま維持されます。
ディレクトリ再構築をすぐに行わない場合は、ソースディレクトリを明示的に設定できます。
```typescript
// nuxt.config.ts
export default defineNuxtConfig({
srcDir: '.',
dir: { app: 'app' },
})
```
この設定により、Nuxt 4はプロジェクトルートからファイルを解決し、Nuxt 3と同じ動作を維持します。
## シングルトンデータフェッチ層とリアクティブキー
Nuxt 4では、`useAsyncData`と`useFetch`のデータ管理方法が根本的に変更されました。同じキーを使用する複数のコンポーネントは、独立したコピーを保持する代わりに、単一のリアクティブ参照を共有するようになります。
```typescript
// app/composables/useProductData.ts
export function useProductData(productId: string) {
return useAsyncData(
`product-${productId}`,
() => $fetch(`/api/products/${productId}`),
{
getCachedData: (key, nuxtApp, ctx) => {
// ctx.causeでフェッチの理由を判別可能
if (ctx.cause === 'refresh:manual') return undefined
return nuxtApp.payload.data[key]
},
},
)
}
```
この新しいデータ層には3つの重要な変更点があります。
- **共有ref**: 2つのコンポーネントで`useProductData('abc')`を呼び出すと、同じ`data`、`error`、`status`のrefが返されます。一方を更新すると、もう一方にも即座に反映されます。
- **自動クリーンアップ**: あるキーを使用する最後のコンポーネントがアンマウントされると、関連データがメモリから解放されます。
- **リアクティブキー**: キーをcomputedまたはrefでラップすると、値の変更時に自動的にデータが再フェッチされます。
`getCachedData`コールバックは、`cause`プロパティ(`'initial'`、`'refresh:hook'`、`'refresh:manual'`、`'watch'`)を持つコンテキストオブジェクトを受け取るようになり、キャッシュデータの提供と新規フェッチの使い分けをきめ細かく制御できます。
> **デフォルト値の変更**
>
> `useAsyncData`/`useFetch`のdataとerrorのデフォルト値が`null`から`undefined`に変更されました。`=== null`チェックを`=== undefined`に更新するか、緩い等価演算子を使用する必要があります。
## Shallow Reactivityによるパフォーマンス最適化
Nuxt 4では、`useAsyncData`と`useFetch`の`data`が`ref`ではなく`shallowRef`をデフォルトで使用するようになりました。Vueはネストされたプロパティを再帰的に追跡しなくなるため、深くネストされたオブジェクトや大規模な配列を含むAPIレスポンスに対して、計測可能なパフォーマンス改善が得られます。
```typescript
// app/pages/dashboard.vue
```
ダッシュボード、商品一覧、記事ページなど、ほとんどの読み取り専用データ表示では、shallow reactivityはコード変更なしで動作します。フォームやネストされたプロパティを直接変更するインタラクティブUIには、`deep: true`オプションが引き続き利用できます。
## TypeScriptコンテキスト分割と型安全性の強化
Nuxt 4では、プロジェクト内の各コンテキストに対して個別のTypeScript設定が生成されます。
- `.nuxt/tsconfig.app.json` — Vueアプリケーションコード用
- `.nuxt/tsconfig.server.json` — Nitroサーバーコード用
- `.nuxt/tsconfig.shared.json` — 共有ユーティリティ用
- `.nuxt/tsconfig.node.json` — ビルド時設定用
この分離により、IDEがクライアントコード内でサーバー専用APIを提案したり、その逆が起きたりすることがなくなります。プロジェクトルートの`tsconfig.json`は、4つすべての設定を参照する構成になります。
```json
{
"files": [],
"references": [
{ "path": "./.nuxt/tsconfig.app.json" },
{ "path": "./.nuxt/tsconfig.server.json" },
{ "path": "./.nuxt/tsconfig.shared.json" },
{ "path": "./.nuxt/tsconfig.node.json" }
]
}
```
CIでの型チェックも変更があります。`vue-tsc`コマンドは、プロジェクト参照を正しく処理するために`-b`フラグ(ビルドモード)が必要になります。
```bash
# 変更前(Nuxt 3)
nuxt prepare && vue-tsc --noEmit
# 変更後(Nuxt 4)
nuxt prepare && vue-tsc -b --noEmit
```
もう1つのTypeScriptの変更点として、`compilerOptions.noUncheckedIndexedAccess`がデフォルトで`true`に設定されるようになりました。配列要素やオブジェクトプロパティへのインデックスアクセスは`T | undefined`を返すようになり、コンパイル時に潜在的なランタイムエラーを検出できます。
## コンポーネント名の正規化とVue Router v5
Nuxt 4.3ではVue Router v5にアップグレードされ、`unplugin-vue-router`への依存が解消されました。ほとんどのアプリケーションでは、このアップグレードは透過的に行われます。
コンポーネントの命名規則が標準化されました。`components/dashboard/MetricsCard.vue`にあるコンポーネントは、``、Vue DevTools、テストユーティリティを含むすべてのコンテキストで一貫して`DashboardMetricsCard`という名前が付けられます。
```vue
```
コンポーネント名フィルターを使用した``を利用しているプロジェクトでは、この新しい命名規則に合わせた更新が必要です。コンテキストによって名前が異なる以前の動作は適用されなくなりました。
## Head管理における破壊的変更への対応
Nuxt 4にはUnhead v2が同梱されており、`useHead`と`useSeoMeta`からいくつかの非推奨プロパティが削除されています。
```typescript
// app/pages/product/[id].vue
```
テンプレートパラメータやエイリアスソートに依存しているプロジェクトでは、これらを明示的なプラグインとしてインストールする必要があります。
```typescript
// app/plugins/unhead.ts
import { TemplateParamsPlugin, AliasSortingPlugin } from '@unhead/vue/plugins'
export default defineNuxtPlugin({
setup() {
const unhead = injectHead()
unhead.use(TemplateParamsPlugin)
unhead.use(AliasSortingPlugin)
},
})
```
> **Nuxt 3のサポート期間**
>
> Nuxt 3は2026年7月31日までセキュリティアップデートと重要なバグ修正を受け続けます。その日以降、Nuxt 3はサポート対象外となります。EOLフレームワーク上で本番アプリケーションを運用することを避けるため、今のうちに移行計画を立てることが推奨されます。
## 移行チェックリストと注意すべきポイント
自動codemodがほとんどの変更を処理しますが、手動対応が必要な項目もあります。
- **`window.__NUXT__`の削除**: `useNuxtApp().payload`に置き換えが必要です。このグローバルオブジェクトはNuxt 4ではハイドレーション後に削除されます。
- **`pages:extend`フック**: ページメタスキャン後に実行される新しい`pages:resolved`フックに切り替えが必要です。
- **`dedupe`ブーリアン**: `refresh({ dedupe: true })`を`refresh({ dedupe: 'cancel' })`に、`false`を`'defer'`に置き換えます。
- **インラインスタイル**: デフォルトではVueコンポーネントスタイルのみがインライン化され、グローバルCSSは別ファイルとして読み込まれます。Nuxt 3の動作に戻すには`features: { inlineStyles: true }`を追加します。
- **`clearNuxtState`**: `undefined`ではなく初期値にリセットされるようになりました。以前の動作が必要な場合は`clearNuxtState('key', { reset: false })`を使用します。
本番アプリケーション向けの実践的な移行手順は以下の通りです。
1. `npx nuxt upgrade --dedupe`を実行し、アプリケーションのビルドを確認
2. codemodを実行: `npx codemod@latest nuxt/4/migration-recipe`
3. ファイルを`app/`に移動(file-structure codemodにより自動化)
4. データフェッチロジックの`null`チェックを`undefined`に更新
5. 正規化された名前で``コンポーネントをテスト
6. CIの型チェックを`vue-tsc -b --noEmit`に更新
7. テストスイート全体を実行し、`noUncheckedIndexedAccess`によって検出されたTypeScriptエラーを修正
VueとNuxtの概念をより深く理解するには、SharpSkillの[Vue/Nuxt面接対策問題](/technologies/vue-nuxt/interview-questions/nuxt-fundamentals)を参照するか、Nuxt 4にも引き継がれるレンダリング戦略の背景として[SSRと静的生成ガイド](/blog/vue-nuxt/nuxt-3-ssr-static-generation)を確認してください。
## まとめ
- Nuxt 4.4(2026年4月時点の最新版)は、`app/`ディレクトリ構造、シングルトンデータフェッチ、分割TypeScriptコンテキストを本番環境対応のデフォルトとして確立しています
- `npx codemod@latest nuxt/4/migration-recipe`コマンドにより、ディレクトリ再構築、非推奨APIの置換、データフェッチの更新が自動化されます
- `shallowRef`によるshallow reactivityは、ほとんどのケースでコード変更不要のままパフォーマンスを改善します
- コンテキストごとの個別TypeScript設定(app、server、shared、node)により、コンテキスト間の型リークが解消され、IDEの補完精度が向上します
- Nuxt 3は2026年7月31日にサポート終了を迎えるため、それ以前の移行がサポート対象バージョンの維持に必要です
- Vue Router v5とUnhead v2はより整理されたAPIを提供しますが、非推奨プロパティの削除に伴い移行時の確認が求められます
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/ja/blog/vue-nuxt/nuxt-4-directory-structure-migration