🍏

移行作業に取り掛かる人のためのVue3移行手順とTips

2023/03/08に公開

はじめに

Vue.js 2 は 2023 年 12 月 31 日に EOL となり、サポートが終了されます。
サポート終了後はセキュリティリリースも行われなくなる予定です。

https://jser.info/2023/01/06/vue-2eol2023-nextauthauth.js-react-nativefirst-class-support-for-typescript/

https://v2.vuejs.org/lts/

Vue 全盛期だった 2019~2020 年辺りに作成されたアプリだとまだまだ Vue2 からアップデートできず、現状大分苦労している現場も多いように考えている。にもかかわらず、Zenn を含め記事が殆ど投稿されていないことに驚きを隠せません(React やりたい気持ちはわかる)。

本記事ではこれからアップデート作業に入る or 対応中の人たちのために、以前筆者が関わっていた案件での経験を基に手順や Tips を紹介します。

思いついたら随時追記していきます。

前提

  • Options API から Composition API への書き換えは行いません。
  • Vue2.6 以前からアップデートが本記事の対象となります。
  • Vue2.7 からのアップデートは対象外とします。
注釈
- ※Options API -> Vue2 でも使用していた`<script>`構文
- ※Composition API -> Vue2.7/Vue3 で使用可能になった`<script setup>`構文

TS 個別対応について

これから紹介する手順の中には「TS のみ対応」の項目が存在します。それらの項目には横に 🔵 をつけています。

公式ガイド

移行ガイドはこちら。残念ながら日本語ページはありません...。

https://v3-migration.vuejs.org/

実は 2 月初旬あたりまで旧 Vue3 日本語サイトで移行ガイドが閲覧出来たのですが、サイトが閉鎖されてしまい、現在は見られなくなりました。
誰か魚拓持っている方がいたら、コメント欄で教えてください...。

移行を始める前に確認しておくこと

Vue3 への移行によって、推奨アプリが色々変更されている。

https://v3-migration.vuejs.org/recommendations.html

- ビルドツール: Vue CLI(Webpack ベース) -> Vite(Not Webpack ベース)
- State 管理 Vuex -> Pinia (※今回は Vuex のままで対応します)
- vscode の拡張機能: Vetur -> Volar

もちろん、vue-router など Vue 関係のライブラリも 3 対応バージョンへのアップデートが必要になる。

(vscode を使用している場合のみ)Vetur -> Volar の注意

  • Vetur -> Vue2 までの拡張機能
  • Volar -> Vue3 以降の拡張機能

となります。両方起動していると設定がコンフリクトしてしまうので、以下の対応が必要です。

https://marketplace.visualstudio.com/items?itemName=Vue.volar

  • Vetur -> disable しておくこと
  • Volar -> enable しておくこと

その他

Vue2.6 より前のバージョンを使っていた場合は、下記内容を確認->修正する必要があります。

https://v3-migration.vuejs.org/migration-build.html#preparations

手順

下記公式ガイドの手順に沿って対応していきます。

https://v3-migration.vuejs.org/migration-build.html

1. 移行ビルドの導入

(公式ガイド手順 1~4)

🔵 型定義ファイルの変更

src フォルダ直下に型定義ファイルを新規作成しておく必要がある。これを定義しておかないと、エディター上で使えなくなるプロパティに打消し線が表示されない。

ファイル名は *.d.ts となっていれば何でも問題ない。

src/vue-compat.d.ts
declare module 'vue' {
  import { CompatVue } from '@vue/runtime-dom'
  const Vue: CompatVue
  export default Vue
  export * from '@vue/runtime-dom'
}

2. 移行ビルドで拾われない箇所の対応および周辺ライブラリのアップデート

まず公式ガイド手順 5 に以下の文章があります。

At this point, your application may encounter some compile-time errors / warnings (e.g. use of filters). Fix them first. If all compiler warnings are gone, you can also set the compiler to Vue 3 mode.

しかし、実際のアプリでは規模に寄りますが警告やエラーを 1 週間そこらで削除することは難しいです。現段階では対応せず、後述の「移行ビルドツールから出てくる警告やエラーの実修正」項目で対応します。

以下は公式ガイド手順 6~10 の内容となります。

移行ビルドで拾われない箇所の対応

移行ビルドで拾われない箇所の対応では以下などが挙げられる。

  • アプリの mount 方法の変更
  • <transition> タグのクラス名の変更

周辺ライブラリのアップデート

周辺ライブラリのアップデートでは以下が対象になる。

  • vuex のバージョンをバージョン 4 に
  • vue-router のバージョンをバージョン 4 に

こんな感じに書き換える。

package.json
"vue-router": "^4.0.0",
"vuex": "^4.0.0"

vue-router

対応量はかなり多め。

https://router.vuejs.org/guide/migration/index.html

特にこのあたりに注意して対応すると良いです。

🔵 vue-router の型定義の変更

また TypeScript を使用している場合はかなり型定義が変更されているため、Vue2 では問題なかったコードがエラーを吐くようになってしまっている(ex: params が string 型だけでなく、string 型の配列も考慮するようになったなど)。

https://router.vuejs.org/guide/migration/index.html#typescript-changes

Vuex

vue-router と比べて対応はかなり小さめ。ここのページに従えば問題ない。
https://vuex.vuejs.org/guide/migrating-to-4-0-from-3-x.html

3. 移行ビルドツールから出てくる警告やエラーの実修正

移行ビルドフラグを使った動作確認

ここで挙げられている ID を指定することで、機能ごとに Vue3 モードの ON/OFF ができます。

値の指定がちょっと紛らわしいのですが、以下となります。

  • true -> Vue3 モード OFF
  • false -> Vue3 モード ON

例えば、COMPONENT_V_MODEL を Vue3 モードにしたい場合はこのように追記します。

src/main.ts
import Vue, { createApp } from 'vue'
...
Vue.configureCompat({
  COMPONENT_V_MODEL: false
})

🔵 コンポーネント定義の変更

Vue.extend は廃止されたことで書き方が変更されています。
Vue2 の頃と比べてかなり型チェックも強化されており、template 側にも厳密な型チェックが入るようになります。

https://ja.vuejs.org/guide/typescript/options-api.html

// example.vue
- import Vue, { PropType } from 'vue'
+ import { defineComponent } from 'vue'
+ import type { PropType } from 'vue'

// TypeScript4.5以降ではこの書き方もOK
// + import { defineComponent, type PropType } from 'vue'

- export default Vue.extend({
+ export default defineComponent({
   ...
])

下記記事では、import に type を載せるメリットが記載されています。
https://azukiazusa.dev/blog/import-type-from-module/#type-modifiers-on-import-names

🔵 plugin の型定義

plugin 機能は ts 環境ではそのままでは型エラーとなってしまうため、d.ts ファイルで事前に型定義しておく必要があります。

https://ja.vuejs.org/guide/typescript/options-api.html#augmenting-global-properties

plugin.d.ts
export {} // <-これを入れないと既存の型が拡張できない

declare module 'vue' {
  interface ComponentCustomProperties {
    $translate: (key: string) => string
  }
}

🔵 その他型定義が必要になる箇所

  • computed の型定義
    • 基本的には書かなくても良いが、ビルドエラーを起こすこともあるので、明示的に型を書いておいた方が良い。
  • イベントハンドラーの型付け
    • React hooks に慣れているとここは特に躓きやすいポイント。 as で型をキャストしてあげる必要がある。
    • $event.target.value とある箇所も出来る可能性あり。

4. Vue3 モードで動かしてみて、OK なら移行ビルドツールを削除

以下コミットを参考に移行ビルドツールのモードを Vue3 モードに変更します。

https://github.com/vuejs/vue-hackernews-2.0/commit/b05d9555f6e115dea7016d7e5a1a80e8f825be52#diff-58e6f63d87181b1c6a8cb6e5f1691df04aa32854456efcd52ca71c8541375d26

エラー・警告が出ないことを確認できたら、以下コミットと同様に移行ビルドツールを削除します。

https://github.com/vuejs/vue-hackernews-2.0/commit/9beb45490bc5f938c9e87b4ac1357cfb799565bd

🔵 型定義ファイル

型定義ファイルについて、このままでは移行ビルド環境のままになってしまっています。
公式ガイドに書かれてなくてえ...って感じですが、Volar のドキュメントに記載されています。

今回作成したものも含めて *.d.ts ファイルはすべて削除して OK です。

https://marketplace.visualstudio.com/items?itemName=Vue.volar

(ここで型定義ファイルを消さないと動かないライブラリも存在します。ex)vue-test-utils など)

これで動作に問題なければ移行は完了です 🎉。

2023 年度末までの移行が難しい場合の対処方法

Vue バージョン 2.7 を使う方法があります。
こちらに関しては 2024 年 3 月中までサポート(Vue バージョン 2.7 のリリースが 2022 年 7 月 1 日から 18 ヶ月間)とアナウンスされています。

3 ヶ月しか延命できませんが、Composition API の使用が出来るなどバージョン 3 に向けた下準備が出来ます。最悪の場合こちらの使用を進めます。

背景など詳細はこちらで見られます。
https://v2.vuejs.org/lts/

以下はオプションの設定手順となります。

ESLint の設定

plugin の切り替え

以下のページに記載されている通り、ESLint の設定ファイルにいる extends の plugin:vue/〇〇plugin:vue/vue3-〇〇 に変更必要があります。これをしないと Vue3 版の Lint エラーが出ません。

https://eslint.vuejs.org/user-guide/#usage

.eslintrc.js
module.exports = {
  extends: [
+    'plugin:vue/vue3-recommended',
-    'plugin:vue/recommended'
  ],
  rules: {
    // ルールを記載
  }
}

その他

※Vite 環境でもライブラリの README に書かれているとおり、おそらく Vue CLI 環境でも問題なく動くと思われる。

Vue CLI 経由で ESLint をダウンロードしていると以下の周辺ライブラリが一緒にダウンロードされているはず。これらも Vue3 向けに最新バージョンへ上げる必要がある。

  • @vue/eslint-config-standard
  • @vue/eslint-config-typescript(TS 環境のみ)

<参考箇所>
https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-plugin-eslint/eslintDeps.js#L23

公式に従い上記 2 パッケージの最新版および、以下のパッケージをインストールする。

- "@rushstack/eslint-patch"

この patch パッケージのおかげで、plugin の追加が不要になるので、以下は使わないのであればアンインストールしても問題ない。

- "eslint-plugin-import"
- "eslint-plugin-node"
- "eslint-plugin-promise"

Vite への移行のススメ

従来、Vue アプリは Vue CLI を使ってアプリが生成されてきましたが、デメリットがたくさん存在します。

https://cli.vuejs.org/

  • すでに Vue CLI の開発がメンテナンスモードに入っており、Vite への移行が推奨されている。
    • セキュリティサポートは続いているものの、活動も鈍化しているおり、いつサポートの終了が出てもおかしくない状況
  • Lint や周辺ライブラリを使う場合、都度専用プラグインをインストールしないといけない上、必ずライブラリ本体の最新バージョンを使えるという保証がない。
    • アプリを中長期的に運用する場合、ライブラリのメンテナンスが困難に。

Vue CLI から Vite に移行することによって、以下のメリットを得ることができます。

https://vitejs.dev/

  • webpack ではなく esbuild/rollup(production 環境のビルド時のみ)を使用されているため、ビルド速度/パフォーマンスの高速化
  • plugin を設定するだけで、煩雑な設定が不要に。
  • 非常に親切な公式ドキュメントがある
  • (Jest を使っている場合)Vitestへの移行が可能。Jest 特有の煩雑な設定が不要に。

ただし Node.js 特有の Common.js から ES Modules 環境に切り替わるため、少しながらデメリットもあります。

  • src フォルダ配下で require 文が使えなくなる。画像を動的に取得している箇所については特に注意が必要。
  • process.env.〇〇 についても、そのままでは使えない。Vite の define 機能で設定しておく必要がある。

Common.js から ES Modules 環境の違いについてはこの記事が詳しい。
https://zenn.dev/yodaka/articles/596f441acf1cf3

Vite の詳しい説明は本記事では触れません。公式ドキュメントや他記事を参考にしてみてください。

Vite への移行手順

Vue2.6 環境のまま Vue Cli から Vite に移行することも出来たが、移行用の Vite の plugin の開発は残念ながら 2022 年末で終了してしまっている。

https://github.com/underfin/vite-plugin-vue2

そのため、Vue3 へのアップデートが完了してからの移行を推奨します。

移行手順はこちらの公式記事が参考になります(Vue2 環境での移行になっているが流れは一緒です。Vite の plugin はこちらのページのものに書き換えておくこと)。

https://vueschool.io/articles/vuejs-tutorials/how-to-migrate-from-vue-cli-to-vite/

その他参考記事

Options API 向けの記事となります。本記事で触れていない項目もたくさん記載されているので参考にしてみてください。

https://zenn.dev/yodaka/articles/84dc716de1d349

Composition API 向けの対応になりますが、一部 Options API でも適用可能です。

https://zenn.dev/ryo_kawamata/articles/vue3-upgrade-guide

GitHubで編集を提案

Discussion