Repository navigation
perf(check): run oxfmt and oxlint in one process (experimental) - #2966
Draft
liangmiQwQ wants to merge 4 commits into
Draft
liangmiQwQ wants to merge 4 commits into
liangmiQwQ wants to merge 4 commits into
Conversation
Runs the oxfmt and oxlint CLIs in one Node process by importing their `dist/cli.js` per step. Each step ends when the event loop drains (`beforeExit`) or when oxfmt calls `process.exit()`, which is patched for the step. The step list comes from stdin as JSON, and a marker with the step's exit code is written to stdout and stderr after each step.
`vp check` used to spawn oxfmt, oxlint, and oxfmt again after `lint --fix`, and each process imported Vite to load vite.config.ts. It now plans the steps up front, sends them to the internal runner, and reports each step as the runner's stdout/stderr markers arrive. The runner stops at the first failing step, matching where reporting returns early.
Member
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
Experimental. This relies on undocumented behavior of the oxfmt and oxlint CLI entries, so it is a stopgap until oxc exports a CLI API.
Description
Today
vp checkspawns oxfmt, then oxlint, then oxfmt again afterlint --fix. Each of those processes starts Node and imports Vite to loadvite.config.ts.This PR makes
vp checkspawn a single internalvp check --rawprocess that runs both tools in-process, so Vite is only imported once there. Output and exit codes are unchanged.How it works:
vp checkplans the steps up front and writes them as JSON to the runner's stdin. Stdin is used because lint-staged can pass enough paths to hit command-line length limits.process.argvand imports the tool'sdist/cli.js. A query string re-evaluates it for the second fmt pass.beforeExit, or when oxfmt callsprocess.exit(), which is patched during the step. On Node < 24.13.1, oxfmt forces an exit 50ms after it finishes. The exit code is read fromprocess.exitCode.vp checksplits each stream at the markers and reports each step as it finishes, just like before.maintotalmainoverheadvp checkvp check --fixThe small project has a
vite.config.tswithfmtandlintblocks and 20 TypeScript files. On this repo,vp check packages/cli/src(type check on) goes from 775ms to 693ms.My Idea:
Honestly, I met a lot of problems while implementing this direction. Oxfmt & Oxlint is not designed for multiple call in the one process. So I used a lot of hacky ways like
beforeExitto handle all of them. I don't think this is the right direction if Vite+ treats it as a long-term approach.However, the benchmark and ~25% performance improvement is still very impressive. That proves reducing multiple
viteimports is still a good direction to makevite-pluspackage faster.Future Plan
As Oxlint & Oxfmt CLI is not designed for multiple calls in the one process, we may still consider whether it is possible to reduce Vite imports in a multi-process environment. Alternatively, we may request Oxc team to provide exported functions to run CLI with a clear lifecycle, but that is obviously not very practical.
There is also an issue, #2920, related to Oxlint and Oxfmt, caused by circular dependency with unlocked
vite-plusversions. This gave me an idea: could we remove thevite-plusdependency from Oxlint and Oxfmt, and pass the config cross-process, like a temp file or env variable or something else? Or, is that possible to remove the child-process invp lintandvp fmt, and inject theresolveConfigfunction at that moment?I hope to take this opportunity to address two issues at once.
🤖 Generated with Claude Code