5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vite+の vp fmtがなんか遅かった理由

5
Posted at

はじめに

最近web開発の統合ツールチェインとしてアルファ版が公開されたばかりのVite+ですが、やたらとフォーマット・リンターが遅いなぁと感じていました。はじめに申し上げますと、原因は分かったんですが解決は出来ていない状況です。

なんか遅いなと感じていた

Vite+を使用する前は、Biomeというフォーマッター・リンターを使用していました。別段遅いと感じたことはなく、やっぱRust早いなぁと弱々プログラマーらしくRustの権威に頭をひれ伏していました。

Vite+に乗り換えて...

vp migrateで既存のコードベースに沿った移行作業をしてくれます。移行作業を終え、とりあえず試しでフォーマットとリンターをまとめて行ってくれるvp checkを実行しました。

で実行時間は?

❯ vp check
VITE+ - The Unified Toolchain for the Web

pass: All 114 files are correctly formatted (1798ms, 16 threads)
pass: Found no warnings, lint errors, or type errors in 61 files (2.1s, 16 threads)

え?遅くね? 114ファイルを16 threadsで 2秒かかってんだけど。Rust使ってるんだよね?

プラス、git hookにvp checkが登録されているので、コミットするたびに2秒の待ち時間が発生します。

時間がかかっている箇所の調査

とりあえず実測

vp checkは中でoxfmtoxlintをラップして実行します。切り分けとしてフォーマットの方を調査していくことにしました。

vp fmtを実行することで、フォーマットオンリーで実行できます。oxfmtを直接実行とどれくらい差分があるかを確認してみました。

vp fmt
❯ vp fmt test.ts 
VITE+ - The Unified Toolchain for the Web

Finished in 1282ms on 1 files using 16 threads.
oxfmt
❯ ./node_modules/.pnpm/node_modules/.bin/oxfmt test.ts 
Finished in 75ms on 1 files using 16 threads.

一目瞭然ですね。比べるまでもないです。
単一ファイルに1秒以上かかっているこの状況なんなんだ、ということで調査をしました。

Claude Codeに調査をぶん投げる

地道な確認作業やデバックなんか一切してないです。味気なくてすみません。

次のステップは Claude Codeがどういう思考回路で動いたか、その作業ログになります。

vp fmt のアーキテクチャを把握する

まず vp fmt が内部で何をしているか、プロセスツリーを確認しました。vp fmt は数秒かかるので、バックグラウンドで起動して子プロセスが立ち上がったタイミングで ps を叩きます。

❯ vp fmt test.ts & sleep 0.5 && ps --forest -o pid,args -g $$
  PID COMMAND
  vp fmt test.ts
   \_ /home/.../.vite-plus/js_runtime/node/24.14.0/bin/node .../vite-plus/dist/bin.js fmt test.ts

vp(Rust バイナリ)は Node.js を子プロセスとして起動し、dist/bin.js に処理を委譲していました。つまり実行フローはこう

vp (Rust binary)
  → Node.js (dist/bin.js)
    → NAPI binding (Rust)
      → oxfmt (子プロセス)

レイヤーを一枚ずつ剥がして差分を取る

プロセスが多段になっているので、外側のレイヤーから順にスキップして実行し、各レイヤーのコストを差分で割り出しました。

# A. vp fmt(全レイヤー)
❯ /usr/bin/time -v vp fmt test.ts
Elapsed: 0:02.76

# B. Node.js bin.js を直接実行(Rust ランチャーをスキップ)
❯ /usr/bin/time -v node dist/bin.js fmt test.ts
Elapsed: 0:02.75

# C. oxfmt 直接(Node.js + bin.js もスキップ)
❯ /usr/bin/time -v oxfmt test.ts
Elapsed: 0:00.17
比較 差分 意味
A - B 0.01s Rust ランチャーのコスト → ほぼゼロ
B - C 2.58s bin.js 内部の処理コスト → ここがボトルネック

bin.jsが圧倒的に処理コストの中心となっていることが確認できます。

bin.js の中で何が遅いのか

bin.js の内部では、NAPI binding 経由で複数の JS resolver 関数が呼ばれます。各 resolver にタイマーを仕込んだところ、犯人は一発で特定できました。

[resolver] fmt(): 0 ms
[resolver] resolveUniversalViteConfig(): 1318 ms   ← 犯人
run() total: 2758 ms

resolveUniversalViteConfig()1.3 秒。Vite+ のソースを読むと、この関数は vite.config.ts から fmt プロパティを取得するために Vite の resolveConfig() をフル実行していました。fmt の設定を読みたいだけなのに、vite.config.ts に書かれた全プラグイン 82 個を import・初期化している。

import { defineConfig } from "vite-plus";

const config = defineConfig({
  fmt: {                        // こいつを読みたいだけなんです...
    ignorePatterns: ["src/routeTree.gen.ts", "src/styles.css", "docs/**"],
    printWidth: 80,
    tabWidth: 2,
    useTabs: false,
    singleQuote: false,
    trailingComma: "all",
  },
  plugins: [                   //  ここに書かれたプラグインが初期化されてしまう...
    devtools(),
    alchemy(),
    tailwindcss(),
    tanstackStart(),
    viteReact(),
    babel({ presets: [reactCompilerPreset()] }),
  ],
});

export default config;

裏を取るため vite.config.tsplugins を空にして再計測をしてみました。

# プラグインあり (82個)
❯ /usr/bin/time -v vp fmt test.ts
Elapsed: 0:02.76

# プラグインなし
❯ /usr/bin/time -v vp fmt test.ts
Elapsed: 0:00.56

プラグインの初期化が行われることで、処理が遅くなっていることが確認できました。

原因まとめ

原因は、vp fmtを実行したとき、fmtプロパティをvite.config.tsから取得するとセットでプラグインまで初期化されてしまうものでした。

  • vp fmtvite.config.ts から fmt 設定を読むために Vite の resolveConfig() をフル実行する
  • プラグインの import と初期化を含むため、ビルド用プラグインが多いプロジェクトほど遅くなる
  • fmt/lint の設定だけ取りたいのにビルドパイプライン全体をロードする設計になっている

対策

現時点では無いです
Vite+ を使う以上避けられないので、改善されるのを待つしかないです。

アルファ版だから仕方なしっていう感じなですかね?あんまりVite+に対する接し方がわからないです。

5
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?