成果物の Diff をまとめてとって TypeScript のアップグレードを円滑にした
最近仕事でやっているプロジェクトの TypeScript のバージョンが 3.9。
そこそこ古くなっているのと、 TS は比較的気軽に上げて良くてバージョンアップの恩恵も高いパッケージなので、MTGが早く終わったスキマ時間で最新に上げてみることにした。
結果として tsc の設定を変えつつ $ diff -r ./before/ ./after/ を活用するとかなり楽に移行できたので、やりかたを残しておく。
手順
やり方を考える
一応社内に Renovate Bot が立っていて、かつそこから出ている Pull Request も存在したものの、流石にビルド成果物を比較しないままエイヤで上げるのは躊躇われる。
TypeScript のバージョンを上げて何かが壊れたことは経験としては一度もないが、一方でその経験則は根拠足り得ないので、一応アプリケーションへの影響を調査して、違いがないことを確認することとした。
TS 本体の変更を全部見に行っても仕方がないので、今回は実際ユーザーに届くコードがどうなっているかを基準にする。
具体的には以下の方法をとることにした。
1. TS v3.9 のまま、プロジェクト内の .tsx? ファイルをすべて TSC にかけたビルド結果を用意する
2. ビルド結果を保持したまま、最新版(TS v4.2)にアップデートする
3. TS v4.2 でプロジェクト内の .tsx? ファイルをすべて TSC にかけたビルド結果を用意する
4. 成果物に違いがないかを確認する
一応他にもアプリケーションとしてのビルド結果を比較する方法も考えたが、 chunk のハッシュなどが変わると比較不可であり、 chunk を作らないとすると、本番ではchunkを分割するのにテストでは分割しないなどをするとそれはもう信頼できるのか。という話になるため、今回は TSC に寄せることに。
1. TS v3.9 のビルド結果の保持
まずは tsconfig.json の設定をテスト用にする。
フレームワークと Integration されている場合は noEmit がついたりしているのでオフにする必要があるが、tsc --initをしている場合は outDir の書き換えだけで OK。
code:tsconfig.json
{
// その他の設定...
"outDir": "_build_v_3_9"
}
TS v4.2 インストール
普通に $ npm i で入れる。
TS v4.2 のビルド結果の保持
同様に outDir を書き換える。
code:tsconfig.json
{
// 略
"outDir": "_build_v_4_2"
}
成果物の比較
今回はココがキモ。diff を使って成果物のコード同士をすべて比較する。
こんな感じでコマンドを実行すると、 ./_build_v_3_9/src/foo.js と ./_build_v_4_2/src/foo.js といった形で相対的に同じパスにあるファイル同士の diff をとってくれる。
code:terminal
$ diff -r ./_build_v_3_9/ ./_build_v_4_2/
結論ほとんど成果物の影響はなく、目視で全部確認できる程度。それも全て polyfill 的な挙動の内部の違いだけだったので、安心して移行に踏み切ることができた。
もちろん実際のコードを見せることはできないが、特徴的なものかつ簡単に再現できるものがあったので一つ。
例えば Array のスプレッドの変換については、このような変更が行われている。
もちろん、実際の動作上の違いはない。
code:javascript
// TS v3.9
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
return to;
// TS v4.2
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += argumentsi.length; for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = argumentsi, j = 0, jl = a.length; j < jl; j++, k++) return r;
おわり
最後は outDir を含め設定を諸々もとに戻して比較ファイルを消して終了。
余談
最近結構技術を移行することが多くて、フレームワークレイヤーなら スナップショットとスナップショットの比較テストを取る みたいなことを結構やっているが、今回はシンプルなビルド結果同士の比較で終わりそう。
ちょうど移行しようと思う前日にも同じケースが有り、楽できる方法がないかなと思って Twitter でこんなこと言ってたが、結論普通に diff コマンドでできた。
https://tweet2image.vercel.app/1397175338094841858.jpg https://twitter.com/potato4d/status/1397175338094841858
https://tweet2image.vercel.app/1397175843311345666.jpg https://twitter.com/potato4d/status/1397175843311345666