SMARTCAMP Engineer Blog

スマートキャンプ株式会社(SMARTCAMP Co., Ltd.)のエンジニアブログです。業務で取り入れた新しい技術や試行錯誤を知見として共有していきます。

Vue3に完全移行した話 〜移行ビルドからの脱却〜

毎度どうも。BALES CLOUD(以下BC)エンジニアのてぃがです。
Vue2のEOLが昨年末に過ぎ去りましたね。
BCもそれに伴って、フロントエンドのVue3への移行を完了しました。
今回はその移行についてお話しします。

何をしたのか?

「移行ビルドを除去して、完全にVue3で動く状態にする作業」です。
Vueの移行ビルドについてはこちらの記事をご参照ください:Vue3にアップグレードしてフロントエンドを改善した話 - SMARTCAMP Engineer Blog

ポイントを先に書いておきます。

  1. できるだけ、先にNodeをアップグレードしておこう
  2. Element Plusには要注意
  3. eslint-plugin-vueを活用しよう
  4. 「どうなればリリースしていいのか?」をしっかり握っておこう
  5. 工数をたっぷり準備しよう

やったこと

  1. braking changesへの対応
    1. eslintによる自動対応
    2. 手動対応
  2. Vue依存パッケージのアップグレード
  3. Migrate buildの除去
  4. 動作確認
  5. リリース

前提

移行作業は、基本的に公式のアップグレードのワークフローに従います。
今回は移行ビルドの導入が完了しているため、ステップ11からの開始です。

また、移行作業はメイン担当者1人とその時々に手の空いているメンバーで対応しました。全体の作業量と効率のバランスをとった形です。
初期段階でわかった作業量を元にタスクを分割し、そのうちのいくつかを他のメンバーに対応してもらいました。
詳しくは後述しますが、移行ビルドは破壊的変更に1つずつ対応できるように設計されているため、タスクもこの粒度にあわせることで容易に分割できました。

0. ねんのためステップ1〜10を確認

移行ビルド導入時の詳細な作業記録が見つけられなかったのもあり、一応確認しました。
こういう作業は面倒でも1つずつ対応した方が、のちに「全然ダメだけど何が問題なのかわからん!」とならずおすすめです。

今回はステップ8が未対応だったので、ここで対応しました。

1. braking changes x eslint

破壊的変更を対応していきます。
eslint-plugin-vueのVue3対応版ルールを活用すると、作業を効率化できます。
(eslintについての説明は割愛させていただきます。ざっくりいうとコードの静的解析です。)
作業は以下の流れです。

  1. eslint-plugin-vueの導入
  2. 自動修正
  3. ルールの一時緩和
  4. 残りを手動修正

1-1. eslint-plugin-vueの導入

通常通りyarn addでプラグインを導入し、設定を書きます。
BCでは、eslintのルールは各種プラグインの推奨に従うという方針を設けています。
よって今回はvue/vue3-recommendedを設定しました。

.eslintrc.js

  extends: [
    'plugin:vue/vue3-recommended',
  ],

1-2. 自動修正

eslint --fixを実施します。
これだけで一部の破壊的変更が自動で修正されます。すばらしい。

1-3. ルールの一時緩和

さて、この時点でeslintをかけると、大量のerrorが発生します。
vue/vue3-recommendedがVue3の破壊的変更をerrorとして定義しているためです。
errorの出ているルールをメモしておきつつ、Vue3関連はいったんすべてwarnに設定します。
(Vue3関係なくerrorになっているルールもありましたが、説明割愛。)

.eslintrc.js

  rules: {
    'vue/no-deprecated-destroyed-lifecycle': 'warn',
    // ...
  },

1-4. 残りを手動修正

ここが一番時間と根気のいる作業です!
破壊的変更を1つずつ修正していきます。

破壊的変更のリストerrorの出ていたルールを突きあわせて確認しながら進めます。
各破壊的変更ごとの作業手順は、ざっくり以下のような感じです。

1: 対応するeslintルールをerrorに戻す

eslintrc.js

  rules: {
    // 'vue/no-deprecated-destroyed-lifecycle': 'warn', // 一時緩和を解除
    // ...
  },

2: 破壊的変更の修正
3: eslintでerrorにならないことを確認
4: 移行ビルドのグローバル設定で該当機能の互換を無効化し、動作確認

main.ts

configureCompat({
  OPTIONS_BEFORE_DESTROY: false,
  OPTIONS_DESTROYED: false
})

すべての互換処理を無効化したら完了です。

2. Vue依存パッケージのアップグレード

Vue2に依存しているパッケージをVue3対応版にアップグレード、または代替パッケージへリプレイスして除去します。

package.jsonのパッケージを1つずつ、真心込めて依存性をチェックします。
「Vue3で動かなくなるかどうか」は案外npmの依存性だけでは判断がつかないので、その時は各公式のリリースノートとかを見ましょう。
対応した限り、一定のバージョン以上からVue3に対応しているものが多かったです。

対象のパッケージがわかったら、パッケージごとの対応内容(アップグレードorリプレイス)を決め、対応していきます。
アップグレード時に破壊的変更があれば、それも対応します。
この際、「いらないパッケージは単純に除去する」という選択肢も持つと良いです。将来のメンテナンスコストが安くなります。

要注意事項ですが、名前にvueがついているパッケージ以外も、Vueのバージョンに依存していることがあります。
各種SaaS用のライブラリなどが入っている場合は要注意です。BCではbugsnagなどが動かなくなりました。

Nodeをアップグレードしておこう

ちなみにですが、BCでは当時Node14が利用されていました。
(もちろん、これがまずいことはわかっています。)
これにより、一部パッケージでは一定バージョン以上からNode14のサポートが終了しており、アップグレードできないという問題が起きました。

BCではこのとき、Vue3対応を優先するため、Nodeのアップグレードは後回しにすることを決定しました。
影響のあったパッケージは、Node14サポートかつVue3対応の最低バージョンまでアップグレードすることで、なんとか対応できたためです。
しかし、これは当時の話です。
現在も、さまざまなパッケージでNode14/16のサポートが終了しつつあり、Nodeのアップグレードを後回しにすることはより困難になっていると思われます。
よって、Vue3アップグレードの前にNodeのアップグレードを完了することを強く推奨します。

また、「対応できた」と言ったものの、実はi18n関連の最新化のみこの問題によって対応しきれませんでした。
幸いクリティカルな問題ではなかったため、Nodeのアップグレードと合わせて後回しとすることになりました。これはおまけとして後述します。

3. Migrate Buildを除去

ここまでの対応で、Vue3への移行は完了しました。
最後に、パッケージ@vue/compatを除去します。
BCでは、ワークフローのステップ4で対応した型の加工を除く必要もありました。

この作業が完了した時点で動作確認し、対応漏れをつみとります。
BCでは、Element Plusが大問題を引き起こしました...。
実はこのパッケージ、移行ビルドに対応していません。
うまく動かない箇所を個別に対応してなんとか動作させていたため、その対応を除くという作業が必要でした。

4. 動作確認

テストフェーズです!

動作確認の前に、「これをクリアすればリリースできる」という基準を設けておきます。
サービスにとって「クリティカルな問題」がなければリリース可能、という基準になるかと思います。
これがなんなのかはサービスによって異なりますが、例えば、ログインができない、商品が表示されない、などです。

基準が決まったら、まずはチーム総動員で動作確認をします。
今回の影響範囲はフロントエンド全般であるため、人海戦術が効きました。
検証用環境で、とくにテストケースは用意せず、全員でいわゆるアドホックテストを実施します。
その結果をまとめ、修正、再度全員で動作確認...というサイクルを、クリティカルな問題がなくなるまで回します。

次に、本番相当環境での動作確認をします。
サービスに「各種SaaS用のライブラリ」など、本番でしか動かないツールが入っていませんか?
忘れずに動作確認しましょう。いや、本当に...🤕。

5. リリース

お疲れ様です、リリースです!
影響範囲が広いため、できるだけユーザーのいない時間帯にリリースするとよいです。

リリースが済んだら速攻で動作確認、あとはお祈りに移行します。
この時点でいくら頑張っていても、細かなバグは出るものです。
くよくよするよりも、なるべく早くバグを発見し、修正、速やかにリリースすることに注力しましょう。
前述の通りbugsnagなどのツールを入れて、エラーを監視できる状態を作っておくのが吉です。

おまけ: どれだけかかったの?

丸三か月です。

移行ビルド除去の調査開始からリリースまでに、これだけかかりました。
通常業務と並行し、主に空き時間に対応していたこともありますが、軽くない工数だと思います。
覚悟と準備の上で臨みましょう。

おまけ: vue-i18nについて

前述の通り、i18n関連の最新化のみ後回しにすることになりました。
さっくりとだけ触れます。

あなたの環境に@intlify/vue-i18n-loadervue-cli-plugin-i18nが入っているなら、その構成は古いです。

前準備として、Nodeをアップグレードします。
Node14や16が入っていたら、最低でも18まで上げましょう。
i18n関連のパッケージがNode18以上にしか対応していないためです。
今上げるならNode20くらいがおすすめです。

準備が整ったら、i18n関連の構成を最新にしましょう。
BCではこうしました。

Before After BCでの役割
vue-i18n vue-i18n i18n core
@intlify/vue-i18n-loader @intlify/unplugin-vue-i18n i18n設定をファイルから読み込めるようにする
vue-cli-plugin-i18n @intlify/eslint-plugin-vue-i18n i18nの静的検査

まとめ&おさらいです!

  1. できるだけ、先にNodeをアップグレードしておこう
  2. Element Plusには要注意
  3. eslint-plugin-vueを活用しよう
  4. 「どうなればリリースしていいのか?」をしっかり握っておこう
  5. 工数をたっぷり準備しよう

いろいろ書いてきましたが、不可能なほど難しいことはなく、地道にやれば必ず完遂できます。
なにより、静的検査はあなたの味方です。eslintを信じ、一緒に歩みましょう。

今回は触れませんでしたが、Vue3にはComposition APIをはじめとした素敵な新機軸がたくさんあります。
早くこちらの世界に来てください。お待ちしております!

以上です。お読みいただきありがとうございました!