フューチャー技術ブログ

Vue.jsを2から3へバージョンアップした話

はじめに

こんにちは。Technology Innovation Group所属の太田寛明です。

新人研修で触れた程度のVue.js経験者の私が、Vueのバージョンアップを行って得た、所感や躓いたポイントを共有します。

経緯

Vue2は2023年12月31日にEnd of Life(EOL)を迎えることになりました。

EOL期日までにVue2をVue3にバージョンアップする必要があります。

今回の対応では、対応内容で紹介する「1. Vue3での動作に必要な変更」をまず最優先で対応し、その後により良いプロダクトとするための取り組みとして「2. Vue3からの新規推奨事項の適用」の対応を行いました。

対応内容

まず最初に今回のVue2から3へのバージョンアップで行った変更の全貌を紹介します。

  1. Vue3での動作に必要な変更
    • Vue本体の更新
    • 周辺パッケージの更新
  2. Vue3からの新規推奨事項の適用
    • ビルドツール変更:Vue CLI ⇒ Vite
      • 起動時間の爆速化1のため実施
    • IDEサポート変更:Vetur ⇒ Vue - Official
      • Veturの無効化2のため実施
      • .vscode/extensions.jsonに、推奨/非推奨の拡張機能を記載して実装3
    • 状態管理ライブラリ変更:Vuex ⇒ Pinia
      • TypeScript化の容易性のため実施
    • テストライブラリ変更:Jest ⇒ Vitest
      • Vite使用時、大幅簡潔化できるため実施
    • API変更4:Options API ⇒ Composition API(script setup
      • TypeScript化の容易性のため実施
    • TypeScript化(環境設定のみ)5
      • コードの型安全性向上のため実施

躓いたポイント

Auth0の移行

周辺パッケージの更新に対応)

Vue2では@auth0/auth0-spa-jsというライブラリを使用して、ラッパーを自作する形で使用することが推奨されていました。
一方でVue3からはauth0-vueというラッパーを内包したライブラリを使用することが推奨されるようになりました。

特にラッパーをカスタマイズせず使用していた場合はそのまま移行すれば問題ないですが、カスタマイズされている場合は大変な作業になると思います。

私の場合は、カスタマイズされたラッパーが使用されていましたが、その後すぐに認証システムがAuth0から変更になる予定であったため、暫定的にライブラリを改造して対応しました。

Vuetifyの移行

周辺パッケージの更新に対応)

振り返りでVuetifyの移行の大変さには触れていますが、ここではとりわけ躓いたポイントに絞って紹介します。

v-date-pickerが取る値の型がString型からDate型に変更

データの受け渡しが当然うまくいかなくなりました。
私の場合、以下状況を踏まえ、Date型用の変数を新たに用意し、watch@update:model-valueを用いて同期させる形で修正しました。

  • 常にv-text-fieldと組み合わせて使用されている
  • データの受け渡しは広い範囲で行われている

実装例:
※比較が容易のため、Options APIで記載しています。
v-menuv-slotの変更も含まれています。

DatePicker.vue
 <script>
+import dayjs from 'dayjs'
export default {
data() {
return {
dateText: '',
+ dateTime: undefined,
+ menuFlg: false,
}
},
+ watch: {
+ dateText() {
+ if (this.dateText) {
+ this.dateTime = dayjs(this.dateText).toDate()
+ } else {
+ this.dataTime = undefined
+ }
+ },
+ },
+ methods: {
+ setDateText() {
+ this.dateText = dayjs(this.dateTime).format('YYYY-MM-DD')
+ this.menuFlg = false
+ },
+ },
}
</script>

<template>
<div>
<!-- dateTextの値が直接変更される場合を再現するボタン -->
<v-btn @click="dateText = '2024-04-01'"> dateText = '2024-04-01' </v-btn>

- <v-menu>
- <template #activator="{ on, attrs }">
+ <v-menu v-model="menuFlg" :close-on-content-click="false">
+ <template #activator="{ props }">
<v-text-field
v-model="dateText"
- v-bind="attrs"
- v-on="on"
+ v-bind="props"
readonly
clearable
></v-text-field>
</template>
<v-date-picker
- v-model="dateText"
- :day-format="(date) => new Date(date).getDate()"
+ v-model="dateTime"
+ @update:model-value="setDateText"
></v-date-picker>
</v-menu>
</div>
</template>

もっとも、タイムゾーンの問題があるため、基本的に日付データの受け渡しは単なる文字列ではなく、タイムゾーン情報を含めて行うのがベターです。

一部コンポーネントが未実装

Vuetifyはまだ一部コンポーネントが未実装であり、該当コンポーネントが実装に含まれる場合は個別で対応が必要になります。

私の場合はv-treeviewが未実装でした(v3.5.9で実装済)。
自作難度がそこまで高くないコンポーネントであったため助かりました。

Vue3に対応していないライブラリの移行

周辺パッケージの更新に対応)

@smartweb/vue-flash-messageの廃止

使用していたフラッシュメッセージ機能を提供してくれるライブラリがVue3では使用できませんでした。

こちらはコンポーネントを自作しても対応できそうでしたが、ちょうど良さそうな代替ライブラリ@alamtheinnov/flashtoastを発見したため、こちらを代わりに使用する形で対応しました。

vue-clipboard2の廃止

使用していたクリップボード機能を提供してくれるライブラリがVue3では使用できませんでした。

Vue3に対応した類似ライブラリはいくつか存在したものの、Web APIのClipboard.writeText()が主要ブラウザのいずれにも対応しており、機能面の差異もほとんどないことから、このAPIを使用して対応する方針に決めました。
(ただし、実際に蓋を開けてみるとプロジェクト内で使用されていなかったため、この対応は不要になりました。)

Yarnがおかしい

ビルドツール変更に対応)

パッケージ管理ツールとしてYarn v1が使用されていたのですが、ViteでファイルをES Modulesとして扱って実行した際に、次のようなエラーに遭遇しました。

推測ですが、CommonJSとES Modulesが併存するライブラリをインストールする際に、パッケージの依存関係次第でうまくいかなくなるようです。

結論としてはYarn v1はそもそも非推奨であるため、npmに移行して対応しました。

Error [ERR_REQUIRE_ESM]: require() of ES Module <path>/node_modules/string-width/index.js

類似のissueは様々に挙げられており(https://github.com/storybookjs/storybook/issues/22431 等)、Yarn v1のバグであると考えられています。

振り返り

私にとって一番大変だったのは、このメジャーバージョンアップを行うにあたり、Vueの何をどのように更新すれば良いのか把握する所だったかと思います。自分的にもここが最も重要な所であると考えていたため、Vueの全体像把握に注力しながら対応内容の洗い出しを行った記憶があります。

対応内容が洗い出された後は、基本的にそれぞれのパッケージに対応する公式ドキュメントに従って移行すれば問題なくVue3化できました。

とはいえ、以下の点で大変であることは間違いないと思います。

  • 公式ドキュメントを逐一確認する必要がある
  • バージョンを上げれば完了するものからソースコードを大きく修正する必要のあるものまで幅広く存在する
  • Vue3に対応していないものも存在する

他と比較しても群を抜いて大変だったのが、Vuetifyの更新でした。

UIを担ってくれるこのライブラリの変更点は、公式ドキュメントですら網羅できないほどあるだけでなく、見た目も変化してしまう箇所があるため、実装箇所を逐一確認して修正する他ありませんでした。(もちろんeslint-plugin-vuetifyを使用すれば幾分か楽できますが、これも変更点を全て網羅しているわけではないため注意が必要です。)

一方で、API変更に伴うテストコードの修正は予想に反してほとんどありませんでした。

さいごに

比較的ざっくりとVueバージョンアップについて経験を踏まえたお話ししました。

詳細な部分については、各々のVueプロジェクトに対し、使用しているライブラリを踏まえ、比較的整備されている公式ドキュメント類とにらめっこしながら、柔軟に対応していくしかないと思いました。

本記事の内容は、これからVueバージョンアップする際に直接的な手助けはしてくれないと思いますが、心構えの助けなんかになればと思っています。

今回のバージョンアップにあたり、Vue.js周りの様々な質問に答えて下さった太田洋介さん、そして本案件を通じて様々なサポートをして下さった澁川喜規さんには深く感謝申し上げます。

最後までありがとうございました。


  1. 1.冗談抜きで100倍くらい早くなりました。
  2. 2.https://ja.vuejs.org/guide/scaling-up/tooling.html#ide-support より、無効化が推奨されています。
  3. 3.デフォルトでは非推奨の拡張機能が使用されていても通知してくれないのでUnwanted Recommendationsという拡張機能も追加しています。
  4. 4.便宜上"Vue3からの新規推奨事項の適用"に記載していますが、公式ドキュメントで名言されている箇所は特に存在していなかったと記憶しています(注目の新機能とは言われています)。
  5. 5.Vue3からTypeScriptへのサポートが強化されたため実施しています。工数の関係でJavaScriptからTypeScriptへ書き換えることはできず、環境設定のみの対応となったため、"(環境設定のみ)"としています。