はじめに
皆さん、こんにちは。株式会社ROXX、backcheck開発チームの山口と申します。 backcheckフロントエンドのTypeScript移行がある程度軌道にのってきたので、ここまでの過程を文書化することにしました。
この記事ではTSの導入までの過程についてかいつまんでお話ししようと思います。
やっていること
Nuxt2系(JavaScript)で書かれたbackcheckのフロントエンドをTypeScriptへマイグレーションしています(2021/11時点で現在進行中)。 IEのサポートの終了+Nuxt3がStableになるタイミングで、Nuxt3+Composition APIへの乗り換えを予定していることから、vue-class-componentやvue-property-decoratorは導入せず、Options APIを使用したまま、TypeScriptのみを導入することとしました。
TypeScript 移行で目指すゴール
「完全 TypeScript 化ではなく、最速で8割 TypeScript 化を目指す」
これをスローガンとして、まずは、普段の開発作業で触る箇所に対して TypeScript でかける状態をなるべく早く用意することをゴールとして考えました。
なぜ TypeScript に書き換えるのか
主には以下を目的としてTypeScriptを導入することにしました。
- 静的解析により、型安全に開発できる
- 型がドキュメントがわりになる
- 早い段階でエラーに気づける
TS移行完了までに相応のコストがかかりますが、移行が完了していなくても部分的に恩恵を受けられることや、長期的にみてコードの品質や開発速度が向上することが移行への後押しになりました。
メンバーのTSキャッチアップ
弊チームでは、実務でTSを書いたことがあるメンバーが12人中7人でした。 このままだと残った5人がフロントのコードが書けなくなる + 実務で使ったことのあるメンバーでも理解度がまちまちであったため、慣れるまでは移行作業を4人参加のモブプロで進めることでキャッチアップすることとしました。
また、モブプロ以外の施策として、TS移行のキックオフ前に、TS未経験者に向けたTypeScriptワークショップを行いました。これにより、モブプロ開始のタイミングで最低限の基本知識は全員が聞いたことがある状態とすることができました。 (TypeScript説明会ではTypeScript Deep Diveをベースに、概要や基本的な機能などについて解説を行いました)
TS環境構築
TypeScript、eslintの設定
キックオフの時点から"strict": true
の状態としています。
vueファイルでmixinsを呼び出している箇所など、型の適用が難しい箇所については、将来的にリファクタリングすることとして、マイグレーションのタイミングではts-ignore
することでエラーを回避するようにしました。
また、TSにマイグレーションする上で、リファクタリングしたくなるコードは、影響範囲が大きくなってしまうので別でタスクを用意し、このプロジェクトではなるべくリファクタリングをしないように決めました。
eslintの設定は、TSマイグレーション未対応のjsやvueファイルでもエラーが出てしまうような項目については、overrideして設定をOFFにしています。
サンプル実装の作成
移行作業の着手前に、1ファイルだけTS化したファイルを用意することで、他ファイルを移行する際の判例としました。実装の例を用意したことで、実装イメージがチームの共通認識としてもてたので、よかったと思います。
TSに移行したファイルのリグレッションテスト
該当画面の挙動にデグレがないかを確認するための、ブラックボックスなテストをQAとして行うこととしました。 その他に、utilsの関数や共通コンポーネントなど、全体影響があるものに関しては、正常系フローの動作確認を行うテストを別途実施することで、デグレが起きていないことを確認することにしました。
移行計画の作成
内容としては開発フローへの乗せ方、作業の進め方の2つを事前に決めました。
開発フローへの乗せ方
backcheck のフロントエンドは JS, vue ファイルあわせて約550ファイル・5万行のコードがあります。 これを80%TSに移行するための超概算で以下の数字がでました。
たとえば... 1スプリントあたりのベロシティの20%を移行作業にわりあてたとすると → 33週かかる 1年は約52週 つまり... 完了までに7ヶ月くらいかかります。
なかなかかかりますね...
TSの移行作業の割合を、1スプリントあたりのベロシティの20%以下に落としてしまうと完了までに年単位でかかってしまうため、プランニングする量としては1スプリントあたりのベロシティの20%を固定枠で設けて、メインのストーリータスクと並行して進めていくというやり方にしました。
移行作業の進め方
当初の計画では、こちらのポッドキャストで説明していた進め方を参考に、影響範囲の少ないところから着手していく計画でした。
api→utils→middleware→vueファイルの順に、細かくマイグレーションしていくことで、依存ファイルの多いvueファイルに着手するタイミングには、依存ファイルが全てTSに置き換わっているイメージです。
しかし、普段の開発の中で触る箇所はある程度絞られています。そのため、TypeScriptマイグレーション専任の担当者を設けずに進めている弊チームでは、影響範囲の少ない箇所からマイグレーションをしても日頃の開発フローの中で恩恵を受けられるまでに相応の時間がかかることに気がつきました。
そのため、普段の開発で触る頻度の高い箇所で、よりはやく恩恵をうけられるように、画面(pagesディレクトリ)単位でチケットを立て、画面に依存しているファイルは全てそのチケットの中でマイグレーションする方針に変更しました。 また、constantsで定義していた定数に関しては事前に一括でTS化を行ってしまいました。
おわりに
実際に移行作業をスタートすると、キックオフ時点に考慮が漏れていて後から決定した内容などもあったりしました。導入準備だけでも3ヶ月ほどかかったので、TS移行の計画を立てる場合はある程度長い目で見ながら進めるのがいいかと思います。
その他、ここはどう進めたの?この設定はどうした?こうした方がよさそう。などご意見、ご質問がありましたらぜひお声がけください。
また、現時点でチーム全員がTSでの実装イメージが持てている状態までTSのキャッチアップが進んだので、今後はモブプロをやめて移行作業の速度アップを考えています。 その辺についてもお時間のある時に記事にしようと思うのでお楽しみに。