はじめに
以下ではPrettierに関する小ネタをまとめる。
設定ファイルを楽に書く
Prettierは以下のいずれかの形式で設定する (Configuration File · Prettierより):
-
package.json
ファイル内の"prettier"
キー。 - JSONかYAMLで書かれた
.prettierrc
ファイル。ファイル名に次の拡張子を付けることも可能:.json/.yaml/.yml
- オブジェクトをエクスポートする
.prettierrc.js
かprettier.config.js
。 - TOMLで書かれた
.prettierrc.toml
ファイル (.toml
拡張子は必須) 。
Prettierのオプションに関しては以下にドキュメントが存在する:
それほど数は多くないためすべて目を通すことも大変ではないが、Prettierのウェブサイト内にはPlaygroundという、ビジュアルに設定ファイルを生成することができる機能があるので、手っ取り早く設定ファイルを作成したい場合は利用するといい。
エディタが左右に分割されており、左側のエディタがフォーマット前のコードを、右側のエディタがフォーマット後のコードをそれぞれ表わしている。タブのサイズやセミコロンの有無など、フォーマット時の設定を決めているのが一番左側にあるペインで、ここで各オプションを選択すると、すぐに右側のエディタにそのオプションを選択した場合のフォーマット結果が反映される。
フォーマット結果に満足できたら、最下部にある"Copy config JSON"をクリックすると、クリップボードに設定用のJSONがコピーされるので、あとは設定ファイルにペーストすればいい。
Playgroundを共有する機能などもあるため、チームで設定を議論するための場としても使うことができる。
eslint-config-prettier
でESLintの不要なルールを取り除く
LinterとしてESLintを併用している人は多いと思うが、フォーマットに関するルールがPrettierの設定と衝突する。こうしたPrettierと競合するルールを無効化するためのライブラリに、eslint-config-prettier
がある。
インストール方法:
$ npm install --save-dev eslint-config-prettier
ESLintの設定ファイルに以下を記述する:
{
"extends": [
"他の設定",
"prettier"
]
}
これでESLintの不要なルールが無効化される。なお、他の設定をオーバーライドできるように、必ず配列の末尾に"prettier"を記入する必要がある。
Husky、lint-staged
との連携
VS Codeなどで"Format On Save"を利用して保存時にフォーマットしている場合は別だが、そうした機能がないエディタを使用している場合に、フォーマットのコマンドを毎度入力することは面倒だ。他のメンバがフォーマットし忘れたコードをPRしてくる可能性もある。ところで、gitにはフック機能があり、これを利用して特定のgit操作時に任意のアクションを実行させることができるので、たとえば「リントがパスしない/フォーマットされていない」コードのコミットを弾くことなどができる。
フックを自前で書くことももちろん可能だが (なお、git init
時に、フックのサンプルが自動的に.git/hooks
に生成されるので、確認しておくといい)、Huskyを使えばフックがより簡単に設定できる。
Huskyをインストールすると、.git/hooks
ディレクトリにファイルが自動的に追加される:
$ ls .git/hooks
applypatch-msg.sample fsmonitor-watchman.sample pre-applypatch.sample prepare-commit-msg.sample pre-rebase.sample update.sample
commit-msg.sample post-update.sample pre-commit.sample pre-push.sample pre-receive.sample
$ npm install --save-dev husky
$ ls .git/hooks
applypatch-msg fsmonitor-watchman.sample post-merge post-update.sample pre-commit prepare-commit-msg.sample pre-rebase.sample sendemail-validate
applypatch-msg.sample post-applypatch post-receive pre-applypatch pre-commit.sample pre-push pre-receive update
commit-msg post-checkout post-rewrite pre-applypatch.sample pre-merge-commit pre-push.sample pre-receive.sample update.sample
commit-msg.sample post-commit post-update pre-auto-gc prepare-commit-msg pre-rebase push-to-checkout
Huskyの設定は、package.json
または.hukyrc
にておこなう。たとえばコミット時にテストを実行したい場合は次のようにする:
// package.json
{
"husky": {
"hooks": {
"pre-commit": "npm test",
}
}
}
あるいは
// .huskyrc
{
"hooks": {
"pre-commit": "npm test"
}
}
これにより、コミット時にテストが実行され、テストが失敗した場合はコミットされないようになる。
Prettierの設定
ESLintやPrettierでチェックをおこなう場合は、package.json
にあらかじめscripts
としてコマンドを登録しておき、それをさらにhooks
として登録するのがいいだろう。たとえば:
// package.json
{
"scripts": {
"lint": "eslint .",
"prettier": "prettier \"**/*.+(js|json)\"",
"format": "npm run prettier -- --write",
"check-format": "npm run prettier -- --list-different",
"validate": "npm run lint && npm run check-format"
}
"husky": {
"hooks": {
"pre-commit": "npm run validate"
}
}
}
ここで、--list-different
はフォーマットされていないファイルがある場合、そのファイル名を出力してエラーコードを返す。これによりフックが止まってくれるため、フォーマットされていないファイルがある場合はコミットできないという仕組みになる。
なお、npm run
の際に--
を用いることで引数を指定することができるので、実際にフォーマットをおこなうformat
と、チェックのみおこなうcheck-format
の重複部分をprettier
としてまとめている。
コミット時に自動フォーマットする
上の設定でフォーマットされていないコードを弾くことができるようになったが、上述したように、自動フォーマットされないエディタを使用している場合は毎度フォーマット用のコマンドを打ち込むことになり面倒だ。そこで、コミット時に自動的にコードをフォーマットすることを次に考える (これをしたいかどうかは人によって好みがあると思うが) 。
上のpre-commit
の設定を素朴にnpm run format
に変更しても、フォーマット後のファイルがgit add
されていないため期待通りの結果とならない。&&
でコマンドをつなぐこともできるが、lint-staged
を使うとより簡単・効率的におこなうことができる。
lint-staged
は、変更された (git add
された) ファイルに対してのみリントをおこなうためのライブラリだ。これにより、リントの実行時間を短くし効率化できる。名前にはlint
と書いてあるが、フォーマッタなど他のコマンドをパイプのようにつなぐこともできる。
インストール方法:
$ npm install --save-dev lint-staged
設定はpackage.json
または.lintstagedrc
にておこなう:
// package.json
{
"lint-staged": {
"*": "your-cmd"
}
}
あるいは
// .lintstagedrc
{
"*": "your-cmd"
}
のようにする。ここで、キーとなっている"*"
は、コマンドの実行対象をglobで指定したものとなる。よって、たとえばJavaScriptとTypeScriptを対象とする場合は
"*.+(js|ts)": "your-cmd"
のようにする。stage
されたファイルが"*.+(js|ts)"
によってフィルタされ、その結果に対して"your-cmd"
コマンドが実行されるという意味だ。"your-cmd"
の部分は配列にして複数のコマンドを記述することもできる。
ESLintとPrettierを組み合わせる場合は次のように書く:
{
"*.+(js)": [
"eslint",
"prettier --write",
"git add"
]
}
また、設定内容をフックとして登録するためには、Huskyの設定ファイルを次のように変更する:
"hooks": {
"pre-commit": "lint-staged"
}
これにより、まずフィルターされたstagedファイルに対してリントが実行され、次にフォーマットが実行され、最後にgit add
されることとなる。ここまででエラーが発生しなければ、実際にコミットが実行される。
実行の順番をまとめると
commitを試みる -> pre-commit hookが呼ばれる -> lint-stagedが実行される -> 対象ファイルに対してリント、フォーマット、git addをおこなう -> 本commit
のようになる。