Prettier やめて dprint にする
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ dprint 良い感じ
◆ ユーザのコードを尊重するので Prettier での問題がほとんど起きない
◆ VSCode 拡張はもう少し便利になってほしい
◆ ユーザのコードを尊重するので Prettier での問題がほとんど起きない
◆ VSCode 拡張はもう少し便利になってほしい
また Prettier に嫌な目にあわされました
以前 (1) (2) からこの辺で Prettier が嫌と言ってますが 他に代替と言える物なかったんですよね
dprint は良さそうと前から期待してたものの 開発中段階とかいうこともあって移行するのは避けてました
README に
という注意書きもありますし
しかし すでに deno の標準フォーマッターとして使われて長いようですし そろそろ使っていこうかなと思います
https://dprint.dev/install/
Prettier は VSCode でのみ使うなら Extension のインストールだけで使えましたが dprint は Rust のプログラムをローカルで動かすみたいなので 別にインストールが必要です
Windows の場合 npm の方法を使っても中では PowerShell スクリプトが実行されるようで 権限不足エラーでした
ポリシー許可した上での ps1 ファイルの実行か exe のインストーラーを使うのが良さそうです
インストールしたら dprint fmt コマンドでフォーマットできますが フォーマットには設定ファイルが必要です
dprint init コマンドで設定ファイルを作れます
グローバルなものではなくてプロジェクト単位で作るもののようです
グローバルな設定ファイルにするなら --config で設定ファイルのパスを指定できるので手動でグローバルな設定ファイルを参照させればできそうです
dprint init を実行すると追加するプラグインを選べます
スペースで x を切り替えられるので 使うものに x をつけます
エンターで確定です
JavaScript のフォーマットは typescript プラグインに含まれてます
選び終わったら dprint.json が作られます
incremental は一括フォーマットするときに前回から変更なかったファイルをスキップしてくれるらしいです
typescript オブジェクトはプラグイン設定用のオブジェクトです
プラグインに dprint-plugin-json も選んでいたら json がキーのオブジェクトも作られます
設定の一覧はここにあります
https://dprint.dev/plugins/typescript/config/
行幅やセミコロンを使うかどうかなどいろいろな設定があります
VSCode 用の Extension があるのでこれを使います
https://github.com/dprint/dprint-vscode
https://marketplace.visualstudio.com/items?itemName=dprint.dprint
JavaScript のフォーマッターを dprint にするために VSCode の設定ファイルに ↓のような設定を追加します
dprint コマンドへのパスを通してない場合は dprint.path に dprint.exe へのパスを設定します
あとは .js ファイルを開いて Alt-Shift-F でフォーマットすると dprint.json での設定通りにフォーマットされます
Prettier の Extension では JavaScript として認識されてるファイルを編集中であればどんな状態でも使えました
しかし dprint ではファイルとして保存されていて さらに dprint.json が見つからないといけません
新規作成してファイルには未保存の状態でコードを書いているとフォーマットできません
他フォーマッターでもこの仕様はものは多いです
ファイルに保存していても dprint.json が見つからないとフォーマットできません
コマンドラインからなら同じフォルダにあれば問題ないのですが VSCode の場合はフォルダを開いている必要もあるようです
フォルダを開かずに単純に .js ファイルを開いただけでは同じフォルダに dprint.json があってもフォーマットできませんでした
グローバル設定を追加する issue もあるので将来的には対応するのかもしれません
https://github.com/dprint/dprint-vscode/issues/13
オプションでは タブを使用してセミコロンは使わないようにしています
比較するだけならインストールしなくてもウェブ上で試すこともできます
Prettier
https://prettier.io/playground
dprint
https://dprint.dev/playground/
全体的には
Prettier はユーザが書いたものを尊重しません
AST から作り直すのが基本で ユーザがわかりやすくするために細かく工夫してもすべて無視されます
minify 済みのコードの復元や 崩れたものを直すときに向いています
dprint はユーザが書いたものを尊重します
できる限りそのままにするのでユーザが書いた工夫は保持されます
基本はそのままで明らかにおかしい部分だけ修正してくれる感じです
そのままでも十分読めるレベルに書かれたものを整えるのに向いています
元
Prettier
dprint
元
Prettier
dprint
Prettier では逆にいらないところでもカッコをつけようとすることがあります
中には読みやすくなるケースもありますが 冗長に感じることのほうが多いです
元
Prettier
dprint
dprint はカッコを残すからといって完全にそのままというわけではありません
ムダな二重括弧などは除去してくれます
元
Prettier
dprint
オブジェクトは例外で複数行なら複数行に 1 行なら 1 行のままにしようとします
全部この方針ならいいのに配列の場合やメソッドチェーンの場合などはそうなりません
dprint はそのままを維持してくれます
元
Prettier
dprint
Prettier では逆に文字数に収まっても改行を追加するケースがあります
一部ライブラリで読みやすくなるかららしいですが その一部ライブラリを使う時以外は余計な機能でしかありません
元
Prettier
dprint
dprint はユーザの書いたものを尊重するので ユーザが複数行していれば複数行にもできます
スイッチケースの対応として 常にインデントをしてくれません
when と then が同列に並ぶのが嫌なので ここは無視する設定が必要そうです
dprint は設定が多いのですがこの部分の設定はなさそうでした
元
Prettier
dprint
無視させるにはコメントで
を入れます
元
Prettier
dprint
個人的には その行を見るだけで次の行に続いてることがわかる Prettier のほうが好きです
dprint は設定で operatorPosition を sameline にすることでオペレータを前の行に持ってこれます
しかし その場合は条件演算子の ? と : も変わってしまいます
これだけは特別扱いしてほしいので 難しいところです
dprint ではこんなバカなことはしません
元
Prettier
dprint
元から変更してないだけではなくて 折り返す必要が出た場合でも余計なスペースを挿入しません
元
dprint
元
Prettier
dprint
一見便利ですが 余計な問題が増えるのでやめて欲しい機能でもありました
例えばこういうものです
white-space を指定してるので value 前後にスペースを入れられたくないのですが 文字数が行の幅を超えていたり HTML のネスト度合いに応じて改行が追加されます
また html という名前にしないといけないので この機能を使って HTML としてフォーマットして欲しいときにはわざわざ html という名前の変数に代入しないといけない制限も出てきます
html としてフォーマットしたいならユーザがコメントでそういう指定をしたときだけにして欲しいです
埋め込み内の折り返しはどっちも同じようでした
一つ文字列として扱いたいので元のコードに改行が無い限り折り返してほしくないのですけど ここも ignore コメントするしかなさそうです
元
Prettier
dprint
やっと心を入れ替えたのかと期待してみたらすごくどうでもいいところでした
そんなところでオプションを入れるくらいならその他の意見が分かれるところはすべてオプション化してほしいですし dprint のようにユーザのコードを尊重するようにしてくれればほとんどの問題はなくなるはずです
オブジェクトのみの特殊な対応をなくして これからも絶対にオプションは入れないくらいの方針だったら まだ一貫してるしと思えましたが中途半端にオプションを追加するようなのでさらに不信感が高まりました
dprint は普通に使えそうなクオリティでしたし 新しく作るものではもう Prettier はいらないかな
以前 (1) (2) からこの辺で Prettier が嫌と言ってますが 他に代替と言える物なかったんですよね
dprint は良さそうと前から期待してたものの 開発中段階とかいうこともあって移行するのは避けてました
README に
This project is under active early development. I recommend you check its output to ensure it's doing its job correctly and only run this on code that has been checked into source control.
という注意書きもありますし
しかし すでに deno の標準フォーマッターとして使われて長いようですし そろそろ使っていこうかなと思います
準備
ドキュメントの通りインストールしますhttps://dprint.dev/install/
Prettier は VSCode でのみ使うなら Extension のインストールだけで使えましたが dprint は Rust のプログラムをローカルで動かすみたいなので 別にインストールが必要です
Windows の場合 npm の方法を使っても中では PowerShell スクリプトが実行されるようで 権限不足エラーでした
ポリシー許可した上での ps1 ファイルの実行か exe のインストーラーを使うのが良さそうです
インストールしたら dprint fmt コマンドでフォーマットできますが フォーマットには設定ファイルが必要です
dprint init コマンドで設定ファイルを作れます
グローバルなものではなくてプロジェクト単位で作るもののようです
グローバルな設定ファイルにするなら --config で設定ファイルのパスを指定できるので手動でグローバルな設定ファイルを参照させればできそうです
dprint init を実行すると追加するプラグインを選べます
>dprint init
Select plugins (use the spacebar to select/deselect and then press enter when finished):
> [x] dprint-plugin-typescript
[x] dprint-plugin-json
[x] dprint-plugin-markdown
[x] dprint-plugin-toml
[ ] dprint-plugin-dockerfile
スペースで x を切り替えられるので 使うものに x をつけます
エンターで確定です
JavaScript のフォーマットは typescript プラグインに含まれてます
選び終わったら dprint.json が作られます
{
"incremental": true,
"typescript": {
},
"includes": ["**/*.{ts,tsx,js,jsx,cjs,mjs}"],
"excludes": [
"**/node_modules"
],
"plugins": [
"https://plugins.dprint.dev/typescript-0.66.0.wasm"
]
}
incremental は一括フォーマットするときに前回から変更なかったファイルをスキップしてくれるらしいです
typescript オブジェクトはプラグイン設定用のオブジェクトです
プラグインに dprint-plugin-json も選んでいたら json がキーのオブジェクトも作られます
設定の一覧はここにあります
https://dprint.dev/plugins/typescript/config/
行幅やセミコロンを使うかどうかなどいろいろな設定があります
VSCode で使う
フォーマッターはコマンドラインとして使うことはあまりなくて 基本はエディタの機能として使いますVSCode 用の Extension があるのでこれを使います
https://github.com/dprint/dprint-vscode
https://marketplace.visualstudio.com/items?itemName=dprint.dprint
JavaScript のフォーマッターを dprint にするために VSCode の設定ファイルに ↓のような設定を追加します
"[javascript]": {
"editor.defaultFormatter": "dprint.dprint"
}
dprint コマンドへのパスを通してない場合は dprint.path に dprint.exe へのパスを設定します
あとは .js ファイルを開いて Alt-Shift-F でフォーマットすると dprint.json での設定通りにフォーマットされます
不便なところ
使ってみて Extension としては Prettier よりも不便なところがいくつかありましたPrettier の Extension では JavaScript として認識されてるファイルを編集中であればどんな状態でも使えました
しかし dprint ではファイルとして保存されていて さらに dprint.json が見つからないといけません
新規作成してファイルには未保存の状態でコードを書いているとフォーマットできません
他フォーマッターでもこの仕様はものは多いです
ファイルに保存していても dprint.json が見つからないとフォーマットできません
コマンドラインからなら同じフォルダにあれば問題ないのですが VSCode の場合はフォルダを開いている必要もあるようです
フォルダを開かずに単純に .js ファイルを開いただけでは同じフォルダに dprint.json があってもフォーマットできませんでした
グローバル設定を追加する issue もあるので将来的には対応するのかもしれません
https://github.com/dprint/dprint-vscode/issues/13
フォーマット比較
実際にフォーマットして Prettier と比較してみますオプションでは タブを使用してセミコロンは使わないようにしています
比較するだけならインストールしなくてもウェブ上で試すこともできます
Prettier
https://prettier.io/playground
dprint
https://dprint.dev/playground/
全体的には
Prettier はユーザが書いたものを尊重しません
AST から作り直すのが基本で ユーザがわかりやすくするために細かく工夫してもすべて無視されます
minify 済みのコードの復元や 崩れたものを直すときに向いています
dprint はユーザが書いたものを尊重します
できる限りそのままにするのでユーザが書いた工夫は保持されます
基本はそのままで明らかにおかしい部分だけ修正してくれる感じです
そのままでも十分読めるレベルに書かれたものを整えるのに向いています
カッコ
Prettier はわかりやすくするためにカッコを付けても結果として意味のないものなら消します元
const x = (foo && bar) && baz
const y = foo || (bar || baz)
Prettier
const x = foo && bar && baz
const y = foo || bar || baz
dprint
const x = (foo && bar) && baz
const y = foo || (bar || baz)
元
const x = a && (b ? c : d)
const y = (a && b) ? c : d
Prettier
const x = a && (b ? c : d)
const y = a && b ? c : d
dprint
const x = a && (b ? c : d)
const y = (a && b) ? c : d
Prettier では逆にいらないところでもカッコをつけようとすることがあります
中には読みやすくなるケースもありますが 冗長に感じることのほうが多いです
元
!function() {
//
}()
Prettier
!(function () {
//
})()
dprint
!function() {
//
}()
dprint はカッコを残すからといって完全にそのままというわけではありません
ムダな二重括弧などは除去してくれます
元
const a = (((1 + 1))) + ((1 + 2))
Prettier
const a = 1 + 1 + (1 + 2)
dprint
const a = (1 + 1) + (1 + 2)
改行
Prettier は指定の行幅に収まるなら積極的に改行を消しますオブジェクトは例外で複数行なら複数行に 1 行なら 1 行のままにしようとします
全部この方針ならいいのに配列の場合やメソッドチェーンの場合などはそうなりません
dprint はそのままを維持してくれます
元
a = {
a: 1,
b: 2,
}
b = [
1,
2,
3,
]
Prettier
a = {
a: 1,
b: 2,
}
b = [1, 2, 3]
dprint
a = {
a: 1,
b: 2,
}
b = [
1,
2,
3,
]
Prettier では逆に文字数に収まっても改行を追加するケースがあります
一部ライブラリで読みやすくなるかららしいですが その一部ライブラリを使う時以外は余計な機能でしかありません
元
fn(x => x, x => x)
Prettier
fn(
x => x,
x => x
)
dprint
fn(x => x, x => x)
dprint はユーザの書いたものを尊重するので ユーザが複数行していれば複数行にもできます
条件演算子のネスト
これはどっちも同じようでしたスイッチケースの対応として 常にインデントをしてくれません
when と then が同列に並ぶのが嫌なので ここは無視する設定が必要そうです
dprint は設定が多いのですがこの部分の設定はなさそうでした
元
const x = aaaaaaaaaaa
? bbbbbbbbbb
? ccccccccccccccc
: dddddddddddddd
: eeeeeeee
? fffffff
: ggggggg
? hhhhhhhh
? iiiiiii
: jjjjjjjj
: kkkkkkkkkkk
Prettier
const x = aaaaaaaaaaa
? bbbbbbbbbb
? ccccccccccccccc
: dddddddddddddd
: eeeeeeee
? fffffff
: ggggggg
? hhhhhhhh
? iiiiiii
: jjjjjjjj
: kkkkkkkkkkk
dprint
const x = aaaaaaaaaaa
? bbbbbbbbbb
? ccccccccccccccc
: dddddddddddddd
: eeeeeeee
? fffffff
: ggggggg
? hhhhhhhh
? iiiiiii
: jjjjjjjj
: kkkkkkkkkkk
無視させるにはコメントで
// prettier-ignore
// dprint-ignore
を入れます
オペレータの位置
オペレータの位置はデフォルトでは dprint は次の行に配置します元
const x = aaaaaaaaaaaa +
bbbbbbbbbbbb +
cccccccccccc +
dddddddddddd +
eeeeeeeeeeee +
ffffffffffff
Prettier
const x =
aaaaaaaaaaaa +
bbbbbbbbbbbb +
cccccccccccc +
dddddddddddd +
eeeeeeeeeeee +
ffffffffffff
dprint
const x = aaaaaaaaaaaa
+ bbbbbbbbbbbb
+ cccccccccccc
+ dddddddddddd
+ eeeeeeeeeeee
+ ffffffffffff
個人的には その行を見るだけで次の行に続いてることがわかる Prettier のほうが好きです
dprint は設定で operatorPosition を sameline にすることでオペレータを前の行に持ってこれます
しかし その場合は条件演算子の ? と : も変わってしまいます
これだけは特別扱いしてほしいので 難しいところです
タブとスペースの混合
Prettier の許せない挙動にタブを使用するように設定しても見た目を揃えるためにスペースも使うというのがありましたdprint ではこんなバカなことはしません
元
longlonglonglong
? {
x: 1
}
: () => {
return 1
}
Prettier
longlonglonglong
? {
x: 1,
}
: () => {
return 1
}
dprint
longlonglonglong
? {
x: 1,
}
: () => {
return 1
}
元から変更してないだけではなくて 折り返す必要が出た場合でも余計なスペースを挿入しません
元
longlonglonglong
? { aaaaaa: 1, bbbbbbb: 2, ccccccc: 3, ddddddd: 4, eeeeee: 5, fffffff: 6, ggggggg: 7 }
: () => { const a = 1; const b = 1; return a + b }
dprint
longlonglonglong
? {
aaaaaa: 1,
bbbbbbb: 2,
ccccccc: 3,
ddddddd: 4,
eeeeee: 5,
fffffff: 6,
ggggggg: 7,
}
: () => {
const a = 1
const b = 1
return a + b
}
テンプレートリテラル
便利機能なのか Prettier では html という名前の関数をテンプレートリテラルのタグとして使うと中身を HTML としてフォーマットします元
const a = html`<div><div>${value}</div><div>aaaaa</div></div>`
Prettier
const a = html`<div>
<div>${value}</div>
<div>aaaaa</div>
</div>`
dprint
const a = html `<div><div>${value}</div><div>aaaaa</div></div>`
一見便利ですが 余計な問題が増えるのでやめて欲しい機能でもありました
例えばこういうものです
const a = html`<div style="white-space: pre-wrap">${value}</div>`
white-space を指定してるので value 前後にスペースを入れられたくないのですが 文字数が行の幅を超えていたり HTML のネスト度合いに応じて改行が追加されます
また html という名前にしないといけないので この機能を使って HTML としてフォーマットして欲しいときにはわざわざ html という名前の変数に代入しないといけない制限も出てきます
html としてフォーマットしたいならユーザがコメントでそういう指定をしたときだけにして欲しいです
埋め込み内の折り返しはどっちも同じようでした
一つ文字列として扱いたいので元のコードに改行が無い限り折り返してほしくないのですけど ここも ignore コメントするしかなさそうです
元
const a = `aaaaaaaaaa ${foo.bar} bbbbbbbbbbbb ${1} ccccccccccccc ${1 + 1} dddddddddddddddd`
Prettier
const a = `aaaaaaaaaa ${foo.bar} bbbbbbbbbbbb ${1} ccccccccccccc ${
1 + 1
} dddddddddddddddd`
dprint
const a = `aaaaaaaaaa ${foo.bar} bbbbbbbbbbbb ${1} ccccccccccccc ${
1 + 1
} dddddddddddddddd`
最近の Prettier
issue でどれだけ不満が出ようが意見が分かれようが頑なにオプションだけは追加しないと主張していたのに最近なぜかオプションの追加があったらしいですやっと心を入れ替えたのかと期待してみたらすごくどうでもいいところでした
そんなところでオプションを入れるくらいならその他の意見が分かれるところはすべてオプション化してほしいですし dprint のようにユーザのコードを尊重するようにしてくれればほとんどの問題はなくなるはずです
オブジェクトのみの特殊な対応をなくして これからも絶対にオプションは入れないくらいの方針だったら まだ一貫してるしと思えましたが中途半端にオプションを追加するようなのでさらに不信感が高まりました
dprint は普通に使えそうなクオリティでしたし 新しく作るものではもう Prettier はいらないかな