flow.js のバージョンアップデートをした話

こんにちは、Progate  の平川です。
本記事は Progate AdventCalendar 3日目の記事になります。

日頃業務ではフロントエンドの実装を担当させていただいています。
今回は先日行った flow.js のバージョンアップについて書いていきたいと思います。

はじめに

最初に弊社のフロントエンドについて簡単にお話させていただきます。

今年で6年目を迎えた弊社はその過程で多種多様な変化や改善が行われながら、現在は react + flux + flow.js でこれらを Rails のテンプレートに読み込む形で構成されています。

長年理想のプロダクトを求めて走り続けてきたのですが、それ故にどうしても開発者体験を向上させる動きは後回しになってしまいがちな状態がずっと続いていました。それがついに今年度、より早く、安定してユーザーさんにプロダクトを届けるために技術的負債を解消して行こうという全社的な方針の決定のもとフロントエンド開発体験向上を目的としたプロジェクトが結成されました。

本記事で書かせていただくのはその一環である flow.js のアップデートに関する話になります。

flow.js とは

flow.js とは facebook 社によって開発された JavaScript の static type checker です。本来動的型付け言語である JavaScript に対して静的な型付けを行うことができます。 近いもので有名なものだとTypeScriptがあります。 

今回のアップデートで行ったこと

flow-bin のバージョンを v0.56 → v0.90までアップデートする
babel のバージョンを v6 → v7までアップデートする

アップデートによって受けられた恩恵

LSP(Language Server Protocol) 対応バージョンになった

そもそも LSP とは?

LSP とは Microsoft によって開発されたエディタや IDE と language server を接続するための protocol です。コードの自動補完や定義元の参照などの機能が抽象化され規格として定められていることで使用者側(エディタや IDE)では LSP に対応した言語であれば、言語ごとに特別な環境を用意しなくてもそれらの便利な機能を利用することができます。ここで LSP について詳しくは触れませんが、興味のある方はこちらからどうぞ。 

flow.js も v0.75 から LSP に対応するようになりました。それによりIDE やエディタでの型補完や変数参照などが可能になり開発体験の向上に大きく繋がりました。

react の新しいメソッドが使えるようになった

flow.js は有名どころの外部パッケージの型定義を自前で抱えています。例えば react や react-dom, node などです。(詳しくはこちらから)ですので react や react-dom のバージョンをどれだけ真摯に追従していたとしても react の新しい機能(createPortal や Fragment など)を使用したくても flow.js の型定義によってはねられてしまう、という中々苦しい状態になってしまっていたのを今回のアップデートで無事解決することができました。

より厳密な型チェックが行えるようになった

flow.js はバージョンが上がるごとに型チェックの精度がどんどん上がっていきます。ここで全部を列挙するのは大変なので1つだけ紹介させていただきます。

こちらより

type Foo = { type: 'A', ... } | { type: 'B', ... }`
function match(foo: Foo) {
  switch (foo.type) {
    case 'C': ... // dead branch, now error! (was allowed previously)
    ...
  }
}

こちらは v0.58~ 解決されたものになります。それまではこのように Union 型に定義されていないものであっても case 文の条件として書くことが許容されていました。

大変だったこと

babel のアップデートが必要になった

flow.js のアップデートをしながら少しずつ厳しくなる型チェックを通るために既存のコードベースへの修正を行う必要がありました。そしてその最中に踏んだのかこちらになります。

github.com

flow.js の change log を見てみると

New/call can now be passed explicit type arguments for polymorphic instantiation. Currently this is supported by the Flow parser.

v0.72~ ポリモーフィックな関数やコンストラクタに対して型を指定できるようになりました。こういった型定義を行い、正しくトランスパイルしようと思うと babel が v7~ でないといけないことに気が付き、flow.js のアップデートは一時中断とし、当時 v6 だった babel のアップデートを行いました。

結果的に babel のアップデートまで行えたので良かったのですが、少なくとも flow.js のアップデートをする、と決めたときには想定できていなかったタスクだったので当初はかなり焦りました。

最後に

本記事ではフロントエンドの開発体験向上の一環で行ったことを少し書かせていただきました。最先端の技術を駆使してこんなものを作りました!みたいなキラキラした感じの記事ではなかったのでそこはすみませんでした。

フロントエンド開発、というと比較的新しい職種ということもあってか、華やかなイメージを持たれる方も一定数いらっしゃるかと思いますが実はこんな地味なタスクを粛々とやっているものもいることがお分かりいただければ幸いです。

今回のアップデートはこれまでプロダクトのメンテナンス作業に関わる機会がなかった自分にとって、とても良い経験になりました。プロダクトのメンテナンス性の大事さの末端くらいは知ることができたと思うのでこれから更に知見を深め、よりチームに貢献していければと思います。

明日は shotaogasawara さんによる Progate AdvendCalendar 4日目です。お楽しみに!