こんにちは、駅メモ!開発チームエンジニアの id:hayayanai です!
私が開発に関わる駅メモ!は、今年で 10 周年を迎えたゲームです。フロントエンドは Vue.js で開発されていて、現在もコード量が増加しています。
今回は、そんな駅メモ!のフロントエンドに vue-tsc を導入して、GitHub Actions で型チェックを実行し、reviewdog に Pull Request で指摘してもらえる状態を作った話を紹介します。
駅メモ!のフロントエンドの状態
はじめに駅メモ!のフロントエンドの簡単な概要を紹介します。
- フレームワークは Angular → Vue 2 → Vue 3
- パッケージマネージャーは Yarn
- Linter や Formatter の GitHub Actions は導入済み
- JavaScript と TypeScript が混在
- JS ファイルでも
@ts-check
で型チェックをしているものもある
- JS ファイルでも
- TSConfig の設定は
strict: false
フロントエンドの規模感は以下の通りです*1。
- Vue コンポーネント数は 1650 コンポーネント
- JS と TS 合わせて 14 万行
- Vue 内の script を含む
また、型周りで次のような課題を抱えていました。
- 型チェックはテキストエディタによるものに頼っている
- ビルド時はトランスパイルのみで型チェックは行われていない
- 実装者のエディタ次第では TS エラーが出なかったり、気づかず対応漏れしたりすることがある
- Remote SSH で開発している都合、変更に対する追従が遅くなると起こりがち
- レビュワーが TS エラーになっていることがわからない
- 2024 年 4 月頃までエディタで import 時の path 解決ができておらず、型定義を書いても参照されない状態だった
- 型を書くことのモチベーションが下がっていた
- 誤った型定義を書いても気づかなかった
- 開発中に実装が変わっても型定義がそのままになっていることがあった
- 型に対する信用が落ちていた
これらの問題を解決し、より堅牢なフロントエンドを開発するため、vue-tsc を導入して、GitHub Actions で型チェックを実行し、reviewdog に PR でコメントしてもらえる状態を作りました。
また、このタイミングで TSConfig の設定を strict: true
に変更しました。
やったこと
1. TypeScript のアップデート
vue-tsc で必要な TypeScript のバージョンは 5.0.0 以上でした。取り組み始めたときはプロジェクトにはバージョン 4.9.5 が入っていて、これでは動作しませんでした。
当然 typescript@latest
までアップデートしたかったのですが、当時は Node.js 16 を使っていたのもあり諸々のパッケージのバージョンが上げられず、結局 5.3.3 となりました。
加えて、ts-loader も古いバージョンから上げられませんでした。この影響を動作確認したところ、型パラメータに const を用いるなどの新しい TS の構文がエラーになってしまうことがわかりました。
しかしながら、今回の目的は型チェック体制を作ることだったため、これらのバージョン問題は別の機会に解決することとしました。既に Vue の Language Server が TS5.0 以上を要求していて、プロジェクト内ではなくエディタ側の TypeScript を使うような設定が入っていたのもスルーした理由の1つです。
2. vue-tsc のインストール
yarn add -D vue-tsc
ちょうど Vue 3.5.0 がリリースされていたため、vue-tsc をインストールした後も関連して bug fix が出ていないかは確認していました。 また、Vue2 から Vue3 への移行作業が並行していて、リリースが近づいていたため Vue3 移行後のコードで正常に動くことを確かめていました。
インストールしたら早速型チェックを実行してみます。
yarn run vue-tsc --noEmit
大量にエラーが出ることを想定していたのですが、数個のエラーが出ただけで終了してしまいました。 プロジェクトや環境によるものが多いかもしれませんが、エラー文を読みつつ、vue-tsc にもっとエラーを出してもらうために直したところを書いておきます。
- プロジェクト内に存在していた壊れた TS ファイルを直す
- 括弧が閉じられていないなど、 TS の構文としておかしなファイルを読み込んでエラー
- 「型定義を書いても参照されない状態」だったため、気づかれず放置されていた
- 数は少なかったので手動で修正
- カスタムディレクティブに不要な記述がされていて TS1003 エラー
- Vue SFC Playground で再現してみた例
- これも数は少なかったので手動で修正
- JavaScript heap out of memory
NODE_OPTIONS
のmax-old-space-size
を増やすことで解決- Mac と CI を実行する Ubuntu でデフォルト値が異なっていて気づくのが遅れた
NODE_OPTIONS='--max-old-space-size=4096' ./node_modules/.bin/vue-tsc
3. tsconfig.json の調整
この機会に合わせて strict: true
に変更しました。経緯は以下の通りです。
- 今まではエラーまみれになるという理由から
strict: false
にして運用していた - 一方で、社内に既に TS を途中導入したうえ
strict: true
で運用していたチームの実績があった - 手元で
strict: true
に変更したら、型の上では null や undefined になり得る状態のまま値を扱っている箇所が多かった- 今まではエンジニアの脳内で null かどうかを考えながらコードを書いていた
- 当然、見落としもあってフロントエラーになることもあった
- 今まではエンジニアの脳内で null かどうかを考えながらコードを書いていた
- チェックを強化したほうが、安全で、余計な思考を減らせると感じた
その他にも細かいオプションを調整しました。
4. GitHub Actions で vue-tsc + reviewdog が実行されるようにする
既に Linter と Formatter の workflow ファイルが存在しており、発火トリガーはほぼ同じものだったため、既存の workflow ファイルに追記しました。 以下に抜粋した設定ファイルとコメントを掲載します。
jobs: build: runs-on: [self-hosted, ubuntu-20.04, large] steps: # ブランチを checkout したり依存を install したりするステップ - uses: reviewdog/action-setup@v1 with: reviewdog_version: latest - name: Run vue-tsc run: | yarn run --silent vue-tsc | reviewdog -name="vue-tsc" -f=tsc -reporter=github-pr-review -filter-mode=file -fail-level=error env: NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }} REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- 上述した
NODE_OPTIONS
についてはpackage.json
側に記述 reporter
はgithub-pr-review
にした- reviewdog の PR コメントに返信できる形式が便利そうだったため
filter-mode
はfile
にした- 変更した行だけでなく、ファイル全体でエラーを出すため
- reviewdog のオプションの詳細は 公式の README を参照
- 実行する self-hosted runners のスペックアップ
- それまでのインスタンスの設定では vue-tsc が完走できずタイムアウトしてしまっていた
- メトリクスを確認したところ RAM が不足していた
- RAM の多いインスタンスが割り当たるように設定を変更して解決
- GitHub-hosted runners を使っている場合は RAM が多くあまり遭遇しないかもしれない
- 使用されたメモリ量は
vue-tsc --diagnostics
等でも確認可能
ここまでの設定で、当初の目的を達成することができました。
5. 運用ルールを決める
チームで以下のようなルールを定めて運用しています。
- 工数やレビュワーと相談しつつ、無理のしない範囲でエラー対応をする
- TS エラーが無い状態から増えたものは必ず対応する
- 基本的に「メリハリのある TypeScript」で運用
まとめ
今回は駅メモ!のフロントエンドに vue-tsc を導入し、GitHub Actions と reviewdog による型チェックの仕組みを導入した話を紹介しました。
導入後、以下のような改善が得られています。
- レビュー時に型エラーを自動的に検出できるようになった
- 開発環境に依存せず、一貫した型チェックが可能になった
strict: true
への移行により、より安全なコードベースを目指すことができるようになった
導入当初に起きていた TS エラーは、エラーコード単位で一括修正を行ったこともあり、1 ヶ月ほどで約 20%削減することができました。
現在はフロントエンドコード品質のメトリクスの集計も開始しており、それを踏まえて今後の方針を検討していきたいと考えています。 また、今回の導入で浮き彫りになった各種ライブラリのバージョン問題も含め、引き続き改善を進めていく予定です。
記事を読んでいただきありがとうございました!
採用募集案内
モバファクでは中途採用・新卒採用ともに絶賛募集中です。会社の情報については、モバファクブログでも発信しています。
技術好きな方、モバファクにご興味をお持ちの方は、ぜひご応募ください!