Nuxt4アップグレードガイドの内容を整理してみた
はじめに
Nuxt3 から Nuxt4 へのアップグレードは、公式の充実したガイドが用意されているため、基本的には記載されている手順に従って作業すれば問題ありません。
Upgrade Guide · Get Started with Nuxt v4
しかし、公式ガイドは分量が多く、項目も多岐にわたるため、全体像を把握するのに時間がかかります。この記事では、実際のアップグレード作業を通じて得た知見をもとに、公式ガイドのどこを重点的に読めばよいかを整理しました。
最終的には公式ガイドを参照して作業することになりますが、事前にこの記事を読むことで全体の作業を効率化できるはずです。
アップグレードの全体的な流れ
Nuxt4 アップグレードは、大きく 3 つのステップに分かれます:
ステップ | 内容 | 目的 |
---|---|---|
1. バージョンアップ | Nuxt4 へのアップデート | 最新バージョンの導入 |
2. 互換性設定の追加 | v3 の挙動を維持する設定を追加 | まず動かすことを優先 |
3. 段階的な移行 | 互換性設定を 1 つずつ外していく | 安全な移行とビッグバンリリースの回避 |
Step 1: Nuxt4 へのバージョンアップ
公式ガイドのコマンドを実行して Nuxt4 にアップデートします。
Step 2: 互換性設定の追加による動作確認
この段階では、既存コードを大量に書き換える前に、まず動かすことが重要です。
- 後述の「v3 の挙動を保持する設定」をすべて追加
- 動作がおかしい部分があれば修正(特に互換性設定がない項目)
- 型エラーが発生する可能性があるので対応
- この時点で一度 PR レビュー&マージできると理想的
Step 3: 段階的な移行
互換性設定を1 つずつ外して動作確認とコード修正を行います。
- codemodも活用
- 影響範囲と原因を特定しやすくなる
- こまめに PR マージができるためビッグバンリリースを避けられる
- 全ての設定を外す必要はないが、将来的には移行が必要
- フラグを残し続けると新機能が利用できず、負債化する可能性が高い
項目別の影響範囲と対応方法
実際のアップグレード作業を通じて感じた影響度をまとめました。
特に影響を受けやすいのは 「New Directory Structure」 と 「Data Fetch(useFetch/useAsyncData)関連項目」 です。
項目名 | Impact Level | 影響を受けるケース(代表例) | codemod | v3 の挙動を保持する設定 |
---|---|---|---|---|
New Directory Structure | Significant | ほぼ全プロダクト | nuxt/4/file-structure |
export default defineNuxtConfig({ srcDir: '.', dir: { app: 'app' } }) |
Singleton Data Fetching Layer | Moderate | 同じキーで useAsyncData /useFetch を複数回呼んでいる |
– | export default defineNuxtConfig({ experimental: { granularCachedData: false, purgeCachedData: false } }) |
Corrected Module Loading Order in Layers | Minimal | Nuxt layers を使用してレイヤーの module 実行順に依存 | – | なし(フックで対応) |
Deduplication of Route Metadata | Minimal |
route.meta.name などを直接参照 |
– | なし |
Normalized Component Names | Moderate | @vue/test-utils の findComponent を使用、<KeepAlive> を使用 |
– | export default defineNuxtConfig({ experimental: { normalizeComponentNames: false } }) |
Unhead v2 | Minimal | useHead でvmid , hid , children , body 等の削除済 API を使用 |
– | export default defineNuxtConfig({ unhead: { legacy: true } }) |
New DOM Location for SPA Loading Screen | Minimal | CSS またはdocument.queryElement で SPA loading template をターゲット |
– | export default defineNuxtConfig({ experimental: { spaLoadingTemplateLocation: 'within' } }) |
Parsed error.data | Minimal |
error.data を手動で JSON.parse
|
– | なし |
More Granular Inline Styles | Moderate | グローバル CSS を使用(nuxt.config.ts のcss プロパティなど) |
– | export default defineNuxtConfig({ features: { inlineStyles: true } }) |
Scan Page Meta After Resolution | Minimal |
pages:extend フックを使用 |
– | export default defineNuxtConfig({ experimental: { scanPageMeta: true } }) |
Shared Prerender Data | Medium | 複数ページで同一データを fetch している | – | export default defineNuxtConfig({ experimental: { sharedPrerenderData: false } }) |
Default data and error values in useAsyncData and useFetch | Minimal |
useAsyncData /useFetch のdata.value またはerror.value がnull かチェック |
nuxt/4/default-data-error-value |
export default defineNuxtConfig({ experimental: { defaults: { useAsyncData: { value: 'null', errorValue: 'null' } } } }) |
Removal of deprecated boolean values for dedupe option | Minimal |
refresh({ dedupe: true/false }) を使用 |
nuxt/4/deprecated-dedupe-value |
なし |
Respect defaults when clearing data | Minimal |
clear /clearNuxtData を使用 |
– | なし |
Alignment of pending value in useAsyncData and useFetch | Medium |
useAsyncData /useFetch のpending を使用 |
– | export default defineNuxtConfig({ experimental: { pendingWhenIdle: true } }) |
Key Change Behavior in useAsyncData and useFetch | Medium |
useAsyncData /useFetch でimmediate:false を指定 |
– | export default defineNuxtConfig({ experimental: { alwaysRunFetchOnKeyChange: true } }) |
Shallow Data Reactivity in useAsyncData and useFetch | Minimal |
data.value の深い reactivity に依存 |
nuxt/4/shallow-function-reactivity |
export default defineNuxtConfig({ experimental: { defaults: { useAsyncData: { deep: true } } } }) |
Absolute Watch Paths | Minimal |
nuxt.hook('builder:watch') でカスタム module が相対パスを期待 |
nuxt/4/absolute-watch-path |
なし |
Removal of window.__NUXT__ object | Minimal | クライアントコードでwindow.__NUXT__ を参照 |
– | なし |
Directory index scanning | Medium | middleware ディレクトリに子ディレクトリが存在 | – | なし |
Template Compilation Changes | Minimal | ファイルシステム上の.ejs テンプレートを直接扱うコード生成 |
nuxt/4/template-compilation-changes |
なし |
Default TypeScript Config Changes | Minimal | TS のnoUncheckedIndexedAccess に引っかかるコード |
– | export default defineNuxtConfig({ typescript: { tsConfig: { compilerOptions: { noUncheckedIndexedAccess: false } } } }) |
TypeScript Config Splitting | Minimal | なし(明示的に設定変更しなければ有効化されない) | – | なし |
Removal of Experimental Features | Minimal | 記載のフラグを使用 | – | なし |
Removal of Top-Level generate Config | Minimal |
nuxt.config.ts のgenerate オプションを使用 |
– | なし |
実体験に基づく感想
小〜中規模なプロダクトであれば、以前の Nuxt2→3 のアップグレードとは打って変わって、非常にスムーズにアップグレードできるケースが多いと感じています。
実際に Vue ファイル数が 60 程度の小規模プロダクトで作業した際は、0.5 人日程度で完了することができました。
Nuxt4 のアップグレードガイドは非常に丁寧に作られており、段階的に移行できる仕組みが整っています。このガイドを参考に、ぜひスムーズなアップグレードを実現してください。
まとめ
- 公式ガイドは充実しているが、全体像把握に時間がかかる
- 「まず動かす」→「段階的移行」の 2 段階アプローチが効果的
- New Directory Structure と Data Fetch 関連が影響を受けやすい
- 小〜中規模プロダクトなら比較的短時間でアップグレード可能
時間がない方は、まずは「New Directory Structure」と「Data Fetch 関連」の項目だけでも事前に確認しておくと、作業時間の短縮につながると思います。
Discussion