こんにちは、食べチョクの開発をお手伝いさせていただいている@ogawa65aです。大きくなり始めたコードベースのリーダビリティを改善するために、コードフォーマッターを導入したいと思ったことはありませんか?しかし、既存のコードベースに一括で自動フォーマット修正を適用するのは少し不安が残りますよね?かといって変更内容をすべて目で確認するのも至難の業です。そこで、食べチョクでは、どのように安全かつ効率的にPrettierを既存のJSに適用したかをご紹介します。Prettierとは設定できるオプションが非常に少ないのが特徴のコードフォーマッターです。Prettierの設計思想は、「コーディングスタイルに関するすべての議論を止める」ことです。たくさんのオプションがあると、どのオプションを有効にするかの議論が始まってしまい本末転倒であるという考えが根底にあります。たくさんのプログラミング言語がサポートされていますが、今回はJSに対象を絞ってお話ししたいと思います。食べチョクでは今年、チームのエンジニアの人数が急激に増加したことに伴って、コードのフォーマットがバラバラになる問題に直面し、Prettierを導入しました。ActionsでPrettierのチェックを走らせるという運用をしていました。既存のファイルのほんの一部を修正しただけで、他の多くの箇所でPrettierによる自動修正が適用され、プルリクの差分がPrettierの修正だらけになってしまって、コードレビューがしにくい状態が続いていました。Prettierによる修正のコミットを分けてレビューすることで問題は多少軽減できましたが、レビューでの指摘事項の修正コミットがさらに上に積まれたりすると、Prettierのコミットが他のコミットに挟まれて、やはりレビューしづらいという問題がありました。してもPrettierの修正が邪魔になってしまう場合は、.prettierignoreに追加して一時的にチェック対象外にしてしまうということもしていましたが、これでは一向に前に進まないという状況でした。既存のコードへのPrettier適用もコツコツ進めていかなければ...、と思いつつ、なんとかうまく効率良く解決できないかと模索していました。コードベース全体に適用してみるとりあえず何が起こるか試しにコードベース全体にPrettierを適用してみました。これではとてもじゃないですが怖すぎてマージできませんし、レビューもできません。changedのタブを開くことすらままなりません。末尾カンマの追加{}の内側のスペースの追加がほとんどで、フォーマッターなので当然といえば当然ですが、ほぼすべて構文上等価な修正であるという点に気が付きました。あれば、**webpackでJSをビルドしてしまえば最終的には同じバンドルができあがるのでは?**という見通しが立ちました。Prettier適用前後でバンドルが一致するか確認してみるPrettierを適用する前後でそれぞれproductionビルドしてできたバンドルがもしも同じであれば、最終的に配布するのはバンドルですから、安心してPrettierを適用できるわけです。以下のように、バンドルは複数できて、ファイル名は[name]-[contenthash].jsとなっています。public/entriesapp1-578d7f8fbcd7d5a41f90.jsapp2-b9a19f69d7d0c0e12917.js...Prettier適用前のpublic/をpublic_before/に退避し、Prettier適用後のpublic/をpublic_after/とリネームします。次に、バンドルが一致するかどうかを確認するスクリプトを用意します。今回は、Rubyでスクリプトを書きました。ここでは、ファイル名の[contenthash]が一致すれば(つまり、ファイル名が一致すれば)、バンドルの内容も同じであることを利用しています。different_bundles.lengthこのスクリプトを実行してみると、約100個あるバンドルの内、なんと95個のバンドルが一致することがわかりました。これで、一致したバンドルのソースコードについては安心してPrettierを適用できることになります。バンドルが変わってしまったソースコードを確認してみるここまでくれば、一致しなかったバンドルのソースコードについてはそのまま残しておいて、後で目視でレビューしても問題ないと思いますが、せっかくなのでもう少し踏み込んでみます。一般に複数のソースコードが1つのファイルにまとめてバンドルされます。変わってしまったバンドルは5つですが、それに対応するソースコードは5個以上あります。この中でもすべてのソースコードのPrettier修正がバンドルを変えてしまう原因になっているわけではないはずです。バンドルを変えてしまっているソースコードを特定したいと思います。実際にバンドルが具体的にどのように変わってしまったかを確認してみます。ここで、Prettier適用前後のバンドルに対して直接diffを取ってしまうと、バンドルは最小化されて1行になってしまっているので、どこが変更されたかわかりません。バンドルに対して一度Prettierを適用してからdiffを取ります。public_after/entries/app1-28b709482ec2bd6e901a.jsそうすると、差分の要因の箇所が表示されます。その差分がどのソースコードから来ているかは、grepして確認すれば多くの場合すぐにわかります。ちなみに、今回は、以下のようなReactのソースコードのPrettierによる修正がバンドルの差分を産んでいるということがわかりました。</span>上記のようにテキスト中の改行で空白を明示的にJSXで挿入していた箇所が、1行にまとめたことで空白が生のテキストとして挿入される形に修正されています。このように、具体的なソースコードの修正箇所を特定することで、そのソースコード以外はPrettierを適用しても問題ないことが確認できます。今回は、変わってしまった5つのバンドルで、結果的に計5つのソースコードが原因で変わってしまっていることがわかりました。最初、724のファイルに変更があった内、この5つを除く719のソースコードに一括でPrettierを適用してもバンドルが変わらないという結果になりました。残り5つのファイルは、別のプルリクでPrettierを適用して目でレビューして、これで無事すべての既存のJSにPrettierが適用できました!最後に手探りで無策の状態からのスタートでしたが、非常に満足な結果になりました。ここで説明した方法は、JS以外のコードやPrettier以外のツール(例えば、sedで一括置換するような場合等)にも適用できるかもしれません。食べチョクのコードベースにはフロント・サーバーサイドともにまだまだ課題がたくさんありますが、試行錯誤や地道な改善を続けていければと思っています。