フロントエンドの小林和弘です。
Vue Fes Japan Online 2022 でお話したことを少し掘り下げようと思います。
薬局のかかりつけ化支援サービス kakari の Vue3 対応の方針についてのお話です。
(Vue2 の LTS 終了まであと 1 年なので「もう Vue3 対応が終わっているよ」というサービスも多いかと思いますが、kakari はこういう方針でやってるよというお話をします)
Vue3 の障壁
kakari では開発初期から、class ベースで Vue の SFC(Single File Component)を書くことができる vue-property-decorator というライブラリが導入されていました。
このライブラリは開発があまり活発ではなく、Vue3 への対応が行われるか怪しい状況にあり、Vue2 から Vue3 へ migration するときの大きな障壁になっています。
GitHub に Vue3 化の issue は立っていますし、Vue3 対応のブランチも作成されていましたが、開発はあまり進んでいないようでした。
vue-property-decorator の元となっている、Vue のコミュニティ内で管理されている vue-class-component も同様の状況です。
vuex、vue-router も Vue3 化に伴い、メジャーバージョンアップする必要があります。
当然、Vue3 の Breaking Changes にも対応しなければなりません。
Vue2 の抑制
kakari で取り組んだのは、Vue2 の依存のコードを増やさないことでした。
Vue3 対応のコードが書ける各種ライブラリのアップデートと導入を進めました。
vue-property-decorator
class ベースのコンポーネントをこれ以上増やさないように、@vue/composition-api の v1.0.0-beta.21 を 2020/12/08 に導入しています。
RC 版を待たずに導入したのは今思えばリスキーな選択でしたが、v1.0.0-beta.1 のリリースが 2020/07/01 で 5 ヶ月間ですごい熱量で bugfix が行われていたので「まあ大丈夫だろう」と楽観的に導入を決定しています。
導入時点で class ベースで書かれたコンポーネントは 134 ファイル存在していましたが、導入してしまえばこの 134 ファイルが増えることはないので、黙々と composition-api に書き換えれば Vue3 の migration に着実に近づきます。
なお現在では composition-api が同梱された vue v2.7.x を利用しているので、@vue/composition-api はプロジェクトからは削除されています。
vuex
composition-api 導入後、Vuex3 での state 管理をやめ、composition-api を利用して state 管理を composable に切り出すようにしました。
state を reactive で管理して、state を更新する関数(Vuex だと actions に相当します)を返却する Object を用意しています。
言葉だと説明がしづらいので、雑なサンプルコードを用意しました。
コンポーネント間での state 参照は provide を使って大元の親コンポーネントから composable の Object を子コンポーネントに流して、子コンポーネント側は inject で Object を受け取るようにしています。
composable の導入は 2021/06/15 で、この時点で Vuex3 の modules は 20 ファイルありましたが、導入後は Vue3 対応で migration が必要な Vuex3 の modules が増えることはありません。
現在では pinia(Vuex5)を導入しているので、composable での state 管理をやめて、新規の Store は pinia で作成しています。
既存の Vuex3 の modules も pinia に置き換えている最中です。
vue-router
vue-router は v3.6.0 から v4 の useRoute、useRouter に対応した composables を提供してくれています。
v3.6.0 にアップデートして、コンポーネント内で Vue インスタンスの $route、$router にアクセスしている部分を useRoute、useRouter に置き換えてしまえば、Vue3 アップデートによる vue-router の修正はほぼ行わなくてよくなります。
kakari では vue-router v3.6.0 を導入して、$route、$router の参照をすべて置き換えました。
安全な migration
Vue Fes Japan Online 2022 では kakari のテスト戦略についてお話しました。
安全な Vue3 への migration が実施できるように E2E の自動テストを導入したというお話をしましたが、それ以外の取り組みとして不足していたコンポーネントのユニットテストを追加・編集してから composition-api へ migration を行っていました。
vue-class-component で Vuex を呼び出す独自の decorator が書かれていたので Vuex の mutation、action、getter が想定したタイミングで呼び出されているかということを確認するユニットテストを中心に書きました。
コンポーネントのみの Jest のカバレッジを、Vue Fes Japan Online 2022 が開催された 2022/10/01 時点と 2022/12/20 時点で比較すると下記のようになっています。各セクションが概ね 8 ~ 14% ほど改善していることがわかります。
2022/10/16 時点で class ベースコンポーネントは 39 ファイルありましたが、2022/12/16 に class ベースコンポーネントはすべて composition-api に置き換えが完了しています。 努力の甲斐あってか、composition-api の migration で大きな事故は起こっていません。
進捗を出す方法
Vue3 のマイグレーションはビジネス的なインパクトが(見た目上)小さいので対応が後手後手になりがちです。
kakari でも運用・新規開発・お問い合わせ対応の合間をみて Vue3 の対応を進めていますが、ただ闇雲に進めていては進捗やモチベーションが下がる一方です。その対策として、Vue3 で必要な対応をすべて洗い出して TODO リストを作成しています。
どのような修正が必要で、さらにどのファイルに修正が必要なのかをリストアップしています。
そして、各ファイルの修正工数と 1 週間で使えそうなリソースからざっくりとロードマップを作成しました。
前述した Vue2 の抑制対応を行って、Vue2 の LTS 終了までにやらなければいけないタスクが確定した(これ以上増えない)状態にしないと、新規追加されたコンポーネントや Store を TODO に追加してロードマップを引き直すという不毛なタスクが発生します。
まずは前述した各ライブラリのアップデートと導入、チーム内での共有を行うことをオススメします。
現状の進捗
残りのタスクは
- Vuex3 → pinia
- node_modules のコンポーネントのアップデート
- Breaking Changes の対応
になっています。
Vuex3 → pinia
Vuex3 の pinia の置き換えは骨が折れますが、安全な migration ができそうな見立てがついています。
まず Vuex3 の modules のユニットテストを作成して、そのテストを pinia のテストに流用するという方法をとっています。
テストファイルの修正差分は 10% 、それも state の参照を $state に変更、dispatch を store のメソッド参照に置き換えるといった軽微なものです。ちょっとしたテストファイルの修正だけで、pinia の store の動作保証ができてしまいます。
実行するコンポーネント側のテストは、vue-property-decorator を composition-api に置き換える際に Vuex3 の mutation や action や getter を呼び出している部分のユニットテストを網羅的に書いていたことが功を奏して、ほぼ修正不要な状態になっています。
node_modules のコンポーネントのアップデート
kakari では UI ライブラリは使っていなかったので node_modules で呼び出している Vue コンポーネントの影響範囲は抑えられてます。
唯一、Drag & Drop を実現するコンポーネントとして Vue.Draggable を利用していますが、こちらは Vue3 バージョンがすでにリリースされていました。
利用しているコンポーネントがメンテナンスされずに Vue3 バージョンが出ていなかった場合は、同じ機能を持つ他のコンポーネントを利用するか、自前でコンポーネントを作成する必要があります。
Breaking Changes の対応
公式の Vue3 Migration Guide には Breaking Changes がリストアップされています。
数は多いですが、対応が必要なものを調べてフィルターしてあげるとそんなにタスク量は多くなかったりします。
kakari では
が対応が必要なタスクでした。
Vue3 対応、そろそろはじめませんか?
Vue2 の LTS 終了は避けようのない未来です。
まずは Vue3 対応のコードを書くことからはじめてみませんか?
是非読者になってください
メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!
■募集ポジションはこちら
https://medpeer.co.jp/recruit/entry/
■開発環境はこちら