Skip to content

perf: oxlint and oxfmt each load vite.config.ts twice per invocation #2698

Description

@ryansuhartanto

Describe the bug

A single vp staged run evaluates the project's vite.config.ts 8 times.

The repro puts a side effect at the top of the config that appends one line per evaluation, recording timestamp, pid and argv:

import { appendFileSync } from 'node:fs';

appendFileSync(
  new URL('./config-loads.log', import.meta.url),
  `load ${Date.now()} pid=${process.pid} argv=${process.argv.slice(1).join(' ')}\n`,
);

export default {
  staged: { '*.ts': 'vp check --fix' },
};

With 3 staged .ts files, one vp staged run produces 8 lines (paths and arguments elided for width):

load ... pid=137436 argv=.bin/vp staged
load ... pid=137479 argv=.bin/vp check --fix f1.ts f2.ts f3.ts
load ... pid=137513 argv=oxfmt/bin/oxfmt --no-error-on-unmatched-pattern f1.ts f2.ts f3.ts
load ... pid=137513 argv=oxfmt/bin/oxfmt --no-error-on-unmatched-pattern f1.ts f2.ts f3.ts
load ... pid=137573 argv=oxlint/bin/oxlint --fix --format=default --no-error-on-unmatched-pattern f1.ts f2.ts f3.ts
load ... pid=137573 argv=oxlint/bin/oxlint --fix --format=default --no-error-on-unmatched-pattern f1.ts f2.ts f3.ts
load ... pid=137654 argv=oxfmt/bin/oxfmt --no-error-on-unmatched-pattern f1.ts f2.ts f3.ts
load ... pid=137654 argv=oxfmt/bin/oxfmt --no-error-on-unmatched-pattern f1.ts f2.ts f3.ts

Four processes load the config, and oxfmt and oxlint each load it twice within the same pid.

Timings from the same repo and the same 3 staged files, averaged over 3 runs (vp v0.3.1, Node v26.8.2, bun 1.4.2):

Time
oxfmt then oxlint, invoked directly 0.045s
vp check --fix, no vite.config.ts present 0.156s
vp check --fix, one-line static vite.config.ts 0.957s
vp check --fix, instrumented vite.config.ts 0.917s
vp staged, no-op task 0.274s
vp staged, running vp check --fix 1.004s

The config used for the 0.957s row has no imports, no plugins and no side effects:

export default { staged: { '*.ts': 'vp check --fix' } };

So the difference between the 0.156s and 0.957s rows is attributable to the presence of the config file rather than to plugin evaluation, and lazyPlugins does not apply since there is nothing to lazy-load. The instrumented config measures the same as the one-line one, so the appendFileSync is not contributing meaningfully.

Adding .oxlintrc.json and .oxfmtrc.json reduces vp check --fix to 0.680s but does not eliminate the loads: the config is still evaluated 7 times in a single run.

vite.config.ts is expected to evaluate once per vp staged run, or the result is cached and reused across the processes that need it.

Reproduction

https://github.com/ryansuhartanto/vite-plus-staged-perf

Steps to reproduce

After cloning:

bun install
./bench.sh

System Info

VITE+ - The Unified Toolchain for the Web

vp v0.3.0

Local vite-plus:
  vite-plus  v0.3.1

Tools:
  vite             v8.2.2
  rolldown         v1.2.7
  vitest           v4.1.11
  oxfmt            v0.66.0
  oxlint           v1.81.0
  oxlint-tsgolint  v7.0.2001
  tsdown           v0.23.0

Used Package Manager

bun

Logs

Validations

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Fields

    Priority

    None yet

    Effort

    None yet

    Target date

    None yet

    Start date

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions