Prettier 3.6: Experimental fast CLI and new OXC and Hermes plugins! · Prettier https://prettier.io/blog/2025/06/23/3.6.0#cli
これ。
今まではprettier@next
で使えてたけど、この度バージョン3.6からlatest
でも利用可能になった。
Experimentalとはいえ
これ自体は息の長い取り組みで、その詳細は2023年の時点で公開されてる。
Prettier’s CLI: A Performance Deep Dive · Prettier https://prettier.io/blog/2023/11/30/cli-deep-dive
なかなか劇的な改善なのではないだろうか。
この2年でどう変わったかも知りたかったけど、その詳細は見つけられなかった。まあ悪くはならんか。
というわけで、よき頃合いならばコードを読もう!というわけで。
prettier
側のエントリーポイント
まずは本体側で、現状は--experimental-cli
というオプションか、PRETTIER_EXPERIMENTAL_CLI
という環境変数で有効化できる。
実体はdynamicImport("../src/experimental-cli/index.js")
と、丸投げしてるだけ。
dynamicImport()
をわざわざ定義してるのは、.cjs
ではimport()
ができないからか。
var dynamicImport = new Function("module", "return import(module)");
なるほど。
src/experimental-cli/index.js
は、単にexport * from "@prettier/cli/bin";
というわけで、本体リポジトリはここまで。
prettier-cli
側のエントリーポイント
エントリーはここの__promise = runBin()
という関数。
このファイルでやってることは、
- CLI引数のパース
- CLI自体は
specialist
- プラグインをロードしてオプションやパーサーの登録
- プラグインはJSで書かれてる前提なので、実装を
import()
してる - https://github.com/prettier/prettier-cli/blob/4b1a66a1b8d7091ba53a37b4762b7863eaf09585/src/utils.ts#L113-L117
- プラグインはJSで書かれてる前提なので、実装を
- パースできたら
import("./index.js")
してrun()
を実行
あらゆる場面の遅延ロードにパフォーマンスへのこだわりを感じる・・・!
index/run()
, index/runGlobs()
標準入力からフォーマット対象を決定するかどうかの分岐のみ。runGlobs()
かrunStdin()
かどっちか。
runGlobs()
を見ていく。
getTargetPaths()
- ファイルの一覧を取得
- ファイルパスだけでなく、ディレクトリまで集めてるのがポイント
- このあたりは冒頭の解説ブログにも書かれてたやつ
.editorconfig
と、.gitignore
と.prettierignore
のフィルタリングKnown
で存在するもののみ、ファイルアクセスする
- 設定ファイルをまとめてハッシュしてキャッシュの準備
makePrettier()
- https://github.com/prettier/prettier-cli/blob/4b1a66a1b8d7091ba53a37b4762b7863eaf09585/src/prettier.ts#L5
- オプションに応じて
prettier
のフォーマット処理の準備 prettier_parallel.js
なら、worktank
によってWorker threadsで実行される(デフォルト)prettier_lazy.js
なら、非同期ロードされるだけ
prettier_serial.js
に実際のフォーマット処理へのマッピングがある- https://github.com/prettier/prettier-cli/blob/4b1a66a1b8d7091ba53a37b4762b7863eaf09585/src/prettier_serial.ts#L30
format()
で、お馴染みのprettier.formatWithCursor()
を呼んでる- これを利用した
check()
やwrite()
といった亜種があるだけ
fileTsPathsTargets
というファイルパス(拡張子)ごとに、オプションやプラグインを用意して、フォーマット処理を呼んでいく- ここは
Promise.allSettled()
でまとめて呼んでた - https://github.com/prettier/prettier-cli/blob/4b1a66a1b8d7091ba53a37b4762b7863eaf09585/src/index.ts#L123
- ここは
- あとは処理結果をまとめてコンソールに出して終わり
以上。
感想
めちゃめちゃシンプルで読みやすかった。
そもそもファイルもこれだけしかないし。
src/
├── bin.ts
├── cache.ts
├── config_editorconfig.ts
├── config_ignore.ts
├── config_prettier.ts
├── constants.ts
├── index.ts
├── known.ts
├── logger.ts
├── logger_transports.ts
├── prettier.ts
├── prettier_cached.ts
├── prettier_lazy.ts
├── prettier_parallel.ts
├── prettier_serial.ts
├── types.ts
└── utils.ts
行数でいうと、.editorconfig
や.ignore
系の設定や、フォーマットオプションの関係解決がメインと言ってもいいくらいだった。
というか、やはりこの設定ファイルまわりは永遠の鬼門らしく、現状たってるIssueもほとんどがそれ関係に見える・・・。
https://github.com/prettier/prettier-cli/issues?q=sort%3Aupdated-desc+is%3Aissue+is%3Aopen
.prettierrc
のフォーマットだけでも、JSONにYAMLにTOMLにJSにTSに・・・大変やもんな・・・。その上override
とかまでできるし。
ちなみに、このCLIのリライトを担当してた@fabiospampinato
氏は、たくさんのモジュールをnpmで公開してる人で、ここでもそれが多分に取り入れられてる。
というか、dependencies
のほとんどが、氏の自作モジュールだったりする。
npmgraph - Dependencies for @prettier/cli https://npmgraph.js.org/?q=%40prettier%2Fcli#zoom=h