## はじめに 現在、[[TypeScript]]の[[フォーマッター]]は主に3つの種類を使い分けている。 | フォーマッター | プロジェクトの性質 | | --------------------------- | --------------------------- | | [[Prettier]]([[prettierd]]) | [[Vue]]や[[Nuxt]]のプロジェクト | | [[Biome]] | [[TypeScript]]ファイルのみのプロジェクト | | [[deno fmt]] | [[Deno]]プロジェクト | [[Deno]]プロジェクトはさておき、それ以外のプロジェクトは[[Vue]]の有無によって[[フォーマッター]]が変わってしまうのが少しもどかしい。 そんなとき、[[VoidZero]]が設立され、そのプロダクトである[[Oxc]]の[[Oxfmt]]が気になった。 <div class="link-card-v2"> <div class="link-card-v2-site"> <img class="link-card-v2-site-icon" src="https://oxc.rs/logo-without-border.svg" /> <span class="link-card-v2-site-name">Oxc</span> </div> <div class="link-card-v2-title"> Oxfmt </div> <div class="link-card-v2-content"> A collection of high-performance JavaScript tools written in Rust </div> <img class="link-card-v2-image" src="https://oxc.rs/og.jpg" /> <a href="https://oxc.rs/docs/guide/usage/formatter"></a> </div> 以下の要件を満たすか調べてみる。 - [[Prettier]]と同程度のフォーマット (公称は95%) - [[prettier-plugin-tailwindcss]]相当の機能 - [[cva]]、[[cn]]関数内のソートも対応 - [[Prettier Plugin Organize Imports]]の機能 - import順の並び替え - 未使用importの削除 ### 環境 | 対象 | バージョン | | ------------- | ------ | | [[macOS]] | 15.7.3 | | [[Oxfmt]] | 0.32.0 | | [[hyperfine]] | 1.20.0 | ## [[TypeScript]]プロジェクトで試す まずは[[Vue]]なし版から。 ```console mkdir oxfmt-sandbox cd oxfmt-sandbox git init bun init . -y bun add -d oxfmt ``` フォーマットは当然のようにかかったのでベンチマークを見る。 ```console $ hyperfine -i --warmup 5 \ 'bunx oxfmt --check index.ts package.json' \ 'bunx prettier -c index.ts package.json' Benchmark 1: bunx oxfmt --check index.ts package.json Time (mean ± σ): 196.0 ms ± 2.3 ms [User: 290.7 ms, System: 138.7 ms] Range (min … max): 192.7 ms … 199.7 ms 14 runs Warning: Ignoring non-zero exit code. Benchmark 2: bunx prettier -c index.ts package.json Time (mean ± σ): 81.7 ms ± 1.0 ms [User: 66.6 ms, System: 15.0 ms] Range (min … max): 80.0 ms … 83.4 ms 30 runs Warning: Ignoring non-zero exit code. Summary bunx prettier -c index.ts package.json ran 2.40 ± 0.04 times faster than bunx oxfmt --check index.ts package.json ``` 2ファイルだと[[Prettier]]の方が速いのかもしれない。[[🦉Silhouette]]で試してみる。 ```console cd ${another-quick-switcher} bun add -D oxfmt @fsouza/prettierd hyperfine -i --warmup 5 \ 'bunx oxfmt --check **/*.ts' \ 'bunx prettier -c **/*.ts' ``` 流石に[[Oxfmt]]の方が速そう。 ```console $ hyperfine -i --warmup 5 \ 'bunx oxfmt --check **/*.ts' \ 'bunx prettier -c **/*.ts' Benchmark 1: bunx oxfmt --check **/*.ts Time (mean ± σ): 73.8 ms ± 4.1 ms [User: 148.6 ms, System: 47.5 ms] Range (min … max): 68.6 ms … 90.5 ms 35 runs Warning: Ignoring non-zero exit code. Benchmark 2: bunx prettier -c **/*.ts Time (mean ± σ): 266.5 ms ± 2.7 ms [User: 380.6 ms, System: 43.1 ms] Range (min … max): 263.1 ms … 271.2 ms 10 runs Summary bunx oxfmt --check **/*.ts ran 3.61 ± 0.20 times faster than bunx prettier -c **/*.ts ``` ちなみに[[Biome]]だと差は2倍くらい。 ```console bun add -D biome $ hyperfine -i --warmup 5 \ 'bunx oxfmt --check **/*.ts' \ 'bunx biome format **/*.ts' Benchmark 1: bunx oxfmt --check **/*.ts Time (mean ± σ): 72.7 ms ± 5.3 ms [User: 140.7 ms, System: 44.6 ms] Range (min … max): 66.7 ms … 100.2 ms 36 runs Warning: Ignoring non-zero exit code. Benchmark 2: bunx biome format **/*.ts Time (mean ± σ): 141.2 ms ± 1.4 ms [User: 129.1 ms, System: 33.9 ms] Range (min … max): 139.2 ms … 145.3 ms 19 runs Summary bunx oxfmt --check **/*.ts ran 1.94 ± 0.14 times faster than bunx biome format **/*.ts ``` [[Oxfmt]]は[[Prettier]]の35倍速いらしいけど、今回だと3倍しか変わらなかったが、そもそもコマンドが妥当ではない気がする。まあ、本題はここではないので一旦スルー。 ただ、[[Neovim]]での1ファイルフォーマットに限っては[[prettierd]]の方がオーバーヘッドが圧倒的に少ないので有利な可能性は残る。 ## 今回はここでやめる [[Oxfmt]]には未来はありつつも、まだalpha版ということもあり、このタイミングで深掘りするのはやめることにした。 - [[Neovim]]だと[[prettierd]]経由の方が速い可能性がある - [[Biome]]のプロジェクトは[[Lint]]と統一されていることにメリットがある - [[Prettier]]のフォーマットチェックはボトルネックになっていない - それよりも型チェックの速度改善が優先事項 - [[tsgo]]、[[Vue Tsgo]]対応を先にやってからのほうがいい ## 調査ログ > [!left-bubble] ![[chappy.webp]] > • 2026-02-15時点の結論です。 > > 要件(TS + Vue、import 整理、Tailwind class 整列)を考えると、実務上の有力候補はほぼ Biome と oxfmt です。 > ただし「第三の良い選択肢」としては、現行 Prettier 構成を維持がまだ最も堅いです(安定性面)。 > > 2択なら、現時点は Biome 推奨です。 > 理由は、oxfmt が公式に alpha で、さらに import/Tailwind sorting が experimental かつ default off だからです。 > 一方で Biome も Tailwind 整列は useSortedClasses(nursery/unsafe fix)で、Prettier plugin と同等ではありません。ここは要注意です。 > > 要するに: > > 1. 安定性最優先: Prettier + 既存3プラグイン 継続 > 2. 2択で選ぶ: Biome > 3. 速度最優先で先行投資: oxfmt を別ブランチでPoC > > 参考(公式): > > - Biome useSortedClasses(nursery / unsafe / formatterではなくlint): https://biomejs.dev/linter/rules/use-sorted-classes/ > - Biome import sorting(unusedは削除しない): https://biomejs.dev/analyzer/import-sorting/ > - Biome Vue/Svelte/Astro full support は experimental opt-in: https://biomejs.dev/reference/configuration/#htmlexperimentalfullsupportenabled > - Biome v2.3(Vue/Svelte/Astro full support experimental): https://biomejs.dev/blog/biome-v2-3/ > - Oxfmt overview(alpha, Prettier互換95%): https://oxc.rs/docs/guide/usage/formatter.html > - Oxfmt sorting(import/Tailwind は experimental・default off): https://oxc.rs/docs/guide/usage/formatter/sorting > - Oxfmt unsupported(Prettier plugins 非対応): https://oxc.rs/docs/guide/usage/formatter/unsupported-features > - dprint plugins(Oxc/Biome/Markup_fmtを組み合わせ可能): https://dprint.dev/plugins/ > [!left-bubble] ![[chappy.webp]] > • 2026-02-15時点の結論です。 > > - oxfmt単体は 2/3 です。 > - Biomeは 条件付きで3/3 です。 > - なので「Biomeは満たさない」は、厳密には NO です。 > > 要件ごとの判定: > > 1. Vue含むPrettier相当フォーマット > > - oxfmt: 概ねYES(Vue対応あり)。ただし alpha。 > - 推測: 「Prettier互換95%」はJS/TSテスト基準なので、Vueでの完全同等までは保証文言なし。 > - Biome: YES(実験機能ON前提)。html.experimentalFullSupportEnabled が必要。 > > 2. Tailwindクラスソート(cva / cn) > > - oxfmt: YES(実験機能ON前提)。experimentalTailwindcss.functions に cn/cva を指定可能(exact match)。 > - Biome: YES(ただしlinterのnursery/unsafe fix)。useSortedClasses の functions で cva など指定可能。 > - 注意: useSortedClasses は「formatter機能」ではなく「linterルール」。 > > 3. 不要import削除 > > - oxfmt: NO(少なくともformatter docs上は import “sorting” のみ)。 > - 推測: 未使用import削除の明示機能は確認できず。 > - Biome: YES(linterの noUnusedImports、unsafe fix)。 > > 要するに: > > - oxfmtを採用するなら、不要import削除は別手段(lint/IDE code action等)が必要。 > - Biomeは満たせるが、unsafe と experimental を受け入れる設計になります。 > > 参考: > > - https://oxc.rs/docs/guide/usage/formatter.html > - https://oxc.rs/docs/guide/usage/formatter/sorting > - https://oxc.rs/docs/guide/usage/formatter/config-file-reference > - https://oxc.rs/docs/guide/usage/formatter/unsupported-features > - https://biomejs.dev/reference/configuration/ > - https://biomejs.dev/blog/biome-v2-3/ > - https://biomejs.dev/ja/linter/rules/use-sorted-classes/ > - https://biomejs.dev/ja/linter/rules/no-unused-imports/ > - https://biomejs.dev/es/analyzer/import-sorting/