はじめに
こんにちは!Incremental Stream Team の @53able です!
今回は現在自分が着手中の TypeScript マイグレーション PJ について書いていきたいと思います!
GameWith の JavaScript
まず GamewWith の JavaScript について紹介していきたいと思います。
JavaScript のボリューム
Cloc というツールを利用し JavaScript のコード行をカウントしてみました。
brew
経由でインストールし、cloc ディレクトリ名
を実行すれば、カウントしてくれます。
brew install cloc cloc /Gamewith
結果は3万6千行でした!
JavaScript のビルドフロー
次に、ビルドフローについて紹介します。
GameWith は Gulp を利用して JavaScript を連結・圧縮しています。
GameWith メインリポジトリでは Vue, React といったフレームワークは導入しておらず、jQuery を利用しています。
※GameWithDesignSystem のリポジトリでは Vue を利用しています
TypeScript 化
今回 GameWith の3万6千行を一度に TypeScript 化し、リリースするのは現実的ではないと判断しました。
そのため、ファイル単位で TypeScript 化して修正をするという影響範囲を小さくしたマイグレーションのフローにしました。
新しいビルドフロー
TypeScript 化の際に長年積み上げてきた Gulp で行っているビルドフローの改修はとてもリスクが大きいため、Gulp は引き続き利用することにしました。
新しいビルドフローは Gulp の前に TypeScript を割り込ませ、既存のフローをできるだけ変更せず導入を考えています。
JavaScript を中間コードとして扱う発想でこの新しいビルドフローを考えました。
マイグレーションの作業フロー
JavaScript -> TypeScript は ts-migration
というツールを利用しました。
今回マイグレーションの作業フローを作るにあたって、以下の作業を行いました。
ts-migration
をいくつか適当なファイルに実行- 生成された TypeScript のファイルを ESLint で整形し既存の JavaScript のファイルと目で差分のチェック
- 次に、自動化したいフローを洗い出すため手動でファイル操作を行いました
ts-migration
はフォルダをターゲットに動作するため、変換用フォルダへ JavaScript をコピーするts-migration
をフォルダ指定で実行し TypeScript へマイグレーション- マイグレーションで変換後の TypeScript を元の JavaScript と同じ場所へコピーする
- TypeScript を
tsc
でコンパイルし、オリジナルの JavaScript が上書きされる ( ここで JavaScript 👉 TypeScript 👉 JavaScript の差分がわかる) - TypeScript 化された JavaScript は ESLint 対象外、ファイルを削除し、
.gitignore
に追加する
ts-migration
は、ディレクトリをターゲットに TypeScript へマイグレーションするので、一旦変換用のディレクトリに作業ファイルをコピーしてマイグレーションを実行するようにしています。
手動で作業を確認後、同等の動作を Node で動作するスクリプトを書き、自動化をしました。
※スクリプトを書く際に js-fire
を利用しました
最終的に完成した自動化のスクリプトは下記のように3つになりました。
// 1. 変換させるたのフォルダへ JavaScript をコピーする npm run migrate -- start /GameWith/xxx.js // 2. `ts-migration` をフォルダ指定で実行し TypeScript へマイグレーション // 3. マイグレーションで変換後の TypeScript を元の JavaScript と同じ場所へコピーする // 4. TypeScript を `tsc` でコンパイルし、オリジナルの JavaScript が上書きされる npm run migrate:sync // 5. TypeScript 化された JavaScript は ESLint 対象外、ファイルを削除し、`.gitignore` に追加する npm run migrate -- end /GameWith/xxx.js
スクリプトは下記のようなイメージです。
const migration = { start: async (jsFile) => { // 1. 変換させるたのフォルダへ JavaScript をコピーする return jsFile; }, end: async (jsFile) => { // 5. TypeScript 化された JavaScript は ESLint 対象外、ファイルを削除し、`.gitignore` に追加する return jsFile; }, }; fire(migration);
おわりに
破壊的なビルドフローの変更ではなく、既存ファイル以前のソースコードを設けることにより、マイグレーションコストを格段に減らしました。
TypeScript へマイグレーションしますが、中間コードが JavaScript なので、既存ファイルと共存は問題ないようにしています。
また、短期間ですべての JavaScript をマイグレーションしてしまうと既存の動いている他案件とコンフリクトし、解消するコストがかなり高くなってしまうため、修正の際に1ファイルずつ案件を担当するエンジニアがマイグレーションできるフローにしました!
まだマイグレーションは始まったばかりですが、完走したいと思います!
Twitter にてテックブログの投稿をツイートしていますので、よろしければフォローをお願いします!
Tweets by gamewith_dev twitter.com
Wanted!
一緒に働く仲間(特にサーバサイドエンジニア)を絶賛募集中です!
以下 Wantedly のページからぜひカジュアル面談へお申し込みください!