Claude CodeでVue 2からVue 3へ移行する — @vue/compatの警告を1種類ずつ消す
Vue 2アプリを@vue/compatの移行ビルドでVue 3へ移すとき、警告IDを1種類ずつ消す順序をCLAUDE.mdに書き、セッションをまたいで進める運用を説明します。
Vue 2のアプリをVue 3へ移すとき、Claude Codeに「全部Vue 3にして」と一度に頼むと、差分が巨大になり、どこで壊れたのか追えなくなります。@vue/compat(移行ビルド)を使えば、Vue 3の上でVue 2の挙動のままアプリを動かし、非互換の箇所を警告として1種類ずつ出せます。この記事では、警告IDを1つだけ「いま消す警告」としてCLAUDE.mdに書き、セッションをまたいで進める運用を、手順と設定例つきで説明します。
@vue/compatは「警告を出すVue 3」で動く
@vue/compat は、設定しだいでVue 2互換の挙動を返すVue 3のビルドです。既定ではVue 2モードで動き、公開されているAPIのほとんどはVue 2と同じに振る舞います。Vue 3で変更・廃止された機能を使うと、実行時に警告が出ます。互換性は、機能ごと、コンポーネントごとに切り替えられます。
この性質が、Claude Codeとの相性を決めます。警告には GLOBAL_MOUNT や INSTANCE_EVENT_EMITTER のような機能IDが付いているので、「今回はこのIDの警告だけをゼロにする」という、終わりが機械的に判定できる単位でタスクを切れます。
Vue公式の移行ビルドのページは、用途として次の3つを挙げています。
- Vue 2アプリをVue 3へ上げる(制約あり)
- ライブラリをVue 3対応にする
- Vue 3をまだ触っていないVue 2開発者が、違いを学ぶ
この記事が扱うのは1つ目です。
着手前に、移行ビルドで上げられるアプリか確かめる
移行ビルドは、Vue 2の公開ドキュメントにあるAPIと挙動だけを対象にしています。ページには、アプリが対象外になりうる条件が3つ書かれています。
- Vue 2の内部APIや未文書の挙動に依存する依存パッケージ。代表例はVNodeの非公開プロパティの利用です。Vuetify・Quasar・ElementUIのようなコンポーネントライブラリに頼っているなら、そのVue 3対応版を待つ形になります
- Internet Explorer 11のサポート。Vue 3はIE11対応を公式に取りやめているので、必要ならVue 2に留まります
- サーバーサイドレンダリング。移行ビルドはSSRにも使えますが、独自SSRの移行は手間が大きく、Nuxt.jsならNuxt 3の対応を待つ形になります
さらに、未文書の挙動に頼るコードは、移行ビルドでも動きません。その挙動に頼らない形へ直します。
Claude Codeに作業を始めさせる前に、package.json の依存を見て、この3条件に当たるものがないかを自分で確かめておきます。ここで外れるアプリを、警告の消し込みで救おうとしても進みません。
もう一つ知っておくと気が楽になる点があります。移行ビルドでアプリが動くようになれば、移行の完了前に本番へ出すこともできます。多少の性能・サイズのオーバーヘッドはあるものの、本番のUXへの影響は目立ちにくい構成です。Vue 2の挙動に頼る依存を、すぐには替えられないときの選択肢です。
互換ビルドを入れるまで(ここは1回で済ませる)
警告を1種類ずつ消す作業の前に、互換ビルドを入れてアプリを起動できる状態にします。公式ページのワークフローは、事前準備から始まります。非推奨の名前付きスロット・スコープ付きスロット構文を使っているなら、先に最新の構文へ直します。この構文は2.6で既に使えます。
次に、package.json で vue を3系に上げ、@vue/compat を同じバージョンで足し、vue-template-compiler があれば @vue/compiler-sfc に置き換えます。公式の例は次の形です(例のバージョンは3.1で、実際の値は自分のプロジェクトの環境に合わせます)。
"dependencies": {
- "vue": "^2.6.12",
+ "vue": "^3.1.0",
+ "@vue/compat": "^3.1.0"
},
"devDependencies": {
- "vue-template-compiler": "^2.6.12"
+ "@vue/compiler-sfc": "^3.1.0"
}ビルド設定では、vue を @vue/compat に別名解決し、コンパイラのオプションで互換モードを有効にします。Viteなら次のとおりです。
// vite.config.js
export default {
resolve: {
alias: {
vue: '@vue/compat'
}
},
plugins: [
vue({
template: {
compilerOptions: {
compatConfig: {
MODE: 2
}
}
}
})
]
}vue-cliやプレーンなwebpackの設定例も同じページにあります。webpackの構成なら vue-loader を ^16.0.0 に上げます。TypeScriptを使っているなら、Vue 3から無くなったdefault exportを補う型宣言ファイル(*.d.ts)も必要です。このファイルには、他に最低1つのトップレベルのimportかexportを入れます(export {} で足ります)。入れないと、型が拡張でなく上書きになります。
ここまでの設定変更は、Claude Codeに依頼してかまいません。ただし変更後はアプリを起動し、コンパイル時の警告やエラーを先に片づけます。公式ページの手順どおり、filters の使用のようなコンパイル時の問題は、この段階で直します。コンパイラ側の警告がすべて消えたら、コンパイラをVue 3モードにもできます。
警告を1種類ずつ消す順序を決める
アプリが起動すると、コマンドラインとブラウザのコンソールの両方に、大量の警告が出ます。公式ページが挙げる進め方のコツは、次のとおりです。
- ブラウザのコンソールで特定の警告だけを絞り込み、1項目ずつ直す。
-GLOBAL_MOUNTのような否定フィルターも使える - 特定の非推奨は、互換設定で抑制できる
- 依存パッケージ(例: vue-router)が出す警告もある。コンポーネントのトレースやスタックトレースで出どころを見分け、まず自分のコードから出る警告を直す
<transition>のクラス名変更は、実行時警告が出ない唯一の項目。.*-enterと.*-leaveのCSSクラスをプロジェクト全体で検索して直す
Claude Codeに渡す作業順は、公式ページのワークフローをそのまま骨格にできます。
警告の消し込みを進める順序
- 1
コンパイル時の警告を片づける
filtersのようなコンパイラ側の問題を先に直します。 - 2
transitionのクラス名を直す
警告が出ない項目なので、検索で見つけます。
- 3
アプリの入口をcreateAppに変える
グローバルなマウントAPIを新しい形にします。
- 4
vuexとvue-routerを4系に上げる
<router-view>と<transition>・<keep-alive>を組み合わせるには、新しいスコープ付きスロットの構文が必要になります。 - 5
残りの警告をIDごとに消す
ここが本題です。次の節で、CLAUDE.mdに書いて回します。
- 6
移行ビルドを外す
すべて消えたら、Vue 3本体に切り替えます。
5番目の「残りの警告」には、順序の手がかりがあります。リファレンス表は、機能を4つの区分に分けています。
| 区分 | 意味 | 表に載っている例 |
|---|---|---|
| 非互換(警告のみ) | 意味先に直さないとエラーになりやすい | 表に載っている例GLOBAL_MOUNT_CONTAINER、COMPILER_V_IF_V_FOR_PRECEDENCE |
| 一部互換(注意点あり) | 意味互換モードでも挙動に差がある | 表に載っている例PROPS_DEFAULT_THIS、INSTANCE_DESTROY |
| 互換のみ(警告なし) | 意味警告が出ない | 表に載っている例TRANSITION_CLASSES |
| 完全互換 | 意味互換モードで同じように動く | 表に載っている例GLOBAL_EXTEND、FILTERS、INSTANCE_EVENT_EMITTER |
「非互換」の区分は、先に直さないとエラーにつながりやすい項目で、6件のIDが並びます。まずここを空にし、その後に「一部互換」へ進む順序が自然です。IDごとの説明は移行ビルドのページの「Feature Reference」にあるので、Claude Codeへの依頼文には、いま消す1つのIDの行だけを貼ります。
「いま消す警告」をCLAUDE.mdに書く
CLAUDE.mdは、Claude Codeが毎セッションの開始時に読む指示ファイルです。同じ訂正を毎回チャットで入力しているなら、それはCLAUDE.mdに書く合図です。移行の現在地も、毎回言い直す情報の代表です。
次は、書き方の一例です。
# Vue 2 → 3 移行(@vue/compat)
## 現在地
- 互換ビルド導入済み(vite.config.js の alias と compatConfig MODE: 2)
- コンパイル時の警告は 0 件
- いま消す警告: INSTANCE_EVENT_EMITTER(vm.$on / $off / $once の廃止)
- 消し終えた警告: GLOBAL_MOUNT, FILTERS
## ルール
- 1回の作業で扱う警告IDは「いま消す警告」の1つだけ
- 他の警告は直さない。見つけたら「次の候補」に書き足すだけにする
- 直したら `npm run test:unit` と `npm run lint` を実行し、結果を報告する
- 終わったら「いま消す警告」を消し終えた側へ移し、次の候補を1つ選ぶ
- vue-router / vuex の警告は、4系に上げるまで触らないこれは例であり、IDや検証コマンドは自分のプロジェクトに合わせて書き換えます。書き方の要点は3つです。
1つ目は、ルールを検証できる形にすることです。ドキュメントは「コードを整えて」より「npm test をコミット前に実行して」のような、確かめられる指示を勧めています。「1つだけ」「他は直さない」は、実際に差分を見て守れたかが判定できる書き方です。
2つ目は、短く保つことです。目安は1ファイル200行以下です。警告の一覧を全部貼りつけず、現在地と次の候補だけを置きます。長くなったらCLAUDE.mdが長すぎるときの警告の意味と直し方を参照してください。
3つ目は、人間向けのメモを分けることです。ブロックレベルのHTMLコメント(<!-- ... -->)は、Claudeのコンテキストに入る前に取り除かれます。移行の経緯や、警告を後回しにした理由のようなメモは、コメントに書けばコンテキストを消費しません。
1回の作業の回し方
セッションの開始時に、Claude Codeへ次のように頼みます。
CLAUDE.md の「いま消す警告」を1つだけ消してください。
まずアプリを起動したときの警告のうち、そのIDの出力箇所を
すべて洗い出し、一覧にしてから直してください。洗い出しを先にさせるのは、範囲を確定してから手を動かさせるためです。警告文はブラウザのコンソールとコマンドラインの両方に出ます。ブラウザ側の警告は、自分でコンソールを絞り込んで文面を貼るのが確実です。依頼文には、警告のIDと出力されたスタックトレースの上位を添えます。
直し終えたら、その場で互換設定を使って「戻りの防止」ができます。公式ページによると、configureCompat に機能IDを false で渡すと、その機能の互換が無効になります。互換が無効なら、その機能はVue 3の挙動で動きます。
import { configureCompat } from 'vue'
configureCompat({
GLOBAL_MOUNT: false,
FILTERS: false
})消し終えたIDをここに足していけば、あとで誰かが古い書き方を持ち込んだとき、警告なしにVue 3の挙動で動くため、古い書き方は動かなくなります。CLAUDE.mdの「消し終えた警告」と、この設定の2か所が対応する形になります。
衝突する機能は、コンポーネント単位でVue 3にする
機能によっては、Vue 2とVue 3で挙動が衝突します。公式ページはレンダー関数のAPI、関数型コンポーネントと非同期コンポーネントの変更を例に挙げています。アプリ全体をいきなり切り替えられないときは、コンポーネントごとに compatConfig オプションでVue 3の挙動を選べます。
export default {
compatConfig: {
MODE: 3, // このコンポーネントだけVue 3の挙動にする
},
// ...
}移行を終えたコンポーネントから MODE: 3 にしていけば、残りのコンポーネントを触らずにVue 3側へ寄せられます。Claude Codeに頼むときは「このファイルだけ」と範囲を絞れるので、差分のレビューも楽です。
セッションをまたぐと何が残り、何が消えるか
移行は数日から数週間にわたるので、セッションが切れる前提で設計します。ドキュメントの説明では、プロジェクト直下のCLAUDE.mdは /compact の後でもディスクから読み直されて再注入されます。会話の中だけで伝えた指示は、圧縮後に失われます。
これが、「いま消す警告」を会話で伝えず、ファイルに書く理由です。残したい情報は、会話でなくCLAUDE.mdに入れます。
CLAUDE.mdが読まれているかが怪しいときは、/context を実行して、Memory filesの一覧に載っているかを見ます。サブディレクトリのCLAUDE.mdは起動時には読まれず、そのディレクトリのファイルをClaudeが読み書きしたときに読み込まれます。移行用のメモは、プロジェクト直下に置くのが確実です。
落とし穴
「いま消す警告」を更新し忘れて、同じ警告を二度直す
CLAUDE.mdは、Claudeに強制的に守らせる設定でなく、コンテキストとして渡す指示です。厳密な遵守は保証されません。作業の終わりにCLAUDE.mdを書き換えるところまでを、ルールの最後の行に含めておきます。それでも更新が漏れたときは、git log で最後のコミットを確認すれば、現在地を復元できます。コミットは警告ID単位に切るのが前提です。
コミットの前後など、必ず特定のタイミングで実行したい処理は、CLAUDE.mdでなくフックで書く選択肢もあります。フックはライフサイクルの決まった場面でシェルコマンドとして動き、Claudeの判断に左右されません。
警告が出なくなったら移行ビルドを外す
すべての警告が消えたら、移行ビルドを外して、Vue 3本体に切り替えます。具体的には、vue から @vue/compat への別名解決と compatConfig を取り除き、@vue/compat を依存から外します。
ただし、Vue 2の挙動に頼る依存が残っていると、この最終段階には進めません。その場合は、依存の更新を待つか、替えるかを決めます。互換ビルドのまま本番に出す選択肢は、前述のとおり存在します。
移行ビルドは、将来の特定のマイナーバージョン以降は配布を止める予定だと、ページに書かれています。ページの記述はVue 3.1の時代のものなので、自分のプロジェクトで使うバージョンや、いま配布されているかどうかは、npmで確認します。
Vue 3に切り替えたあとは、型検査とテストを検証コマンドとして固定します。その設定はClaude CodeでVue 3アプリを開発するで扱っています。同じように「破壊的変更を1つずつ潰す」型の移行は、Jest 30へのアップグレードやTailwind v4への移行でも使えます。大規模な書き換え全般の進め方はレガシーコード移行の進め方にまとまっています。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。