In the first chapter, we looked at why Vite+ exists.
The short version was:
Modern JavaScript projects use many excellent tools, but connecting and maintaining all those tools can become complicated.
Vite+ tries to bring several of those tools together behind one workflow.
But this raises another question:
What is actually inside Vite+?
If you see:
vp dev
vp test
vp check
vp build
what happens behind those commands?
Let's open the toolbox.
Vite+ is not one giant tool
The first thing to understand is that Vite+ isn't a single replacement for everything.
It brings together several tools, each with a specific job.
A simplified view looks like this:
Vite+
|
+--------------+--------------+
| | |
Development Quality Testing
| | |
Vite Oxlint / Oxfmt Vitest
|
Building
|
Rolldown
+-----------------------------+
|
Libraries
|
tsdown
+-----------------------------+
|
Tasks
|
Vite Task
Each tool solves a different problem.
The important part is that Vite+ gives you a consistent way to work with them.
Let's go through them one by one.
1. Vite — Development
Let's start with the tool most developers already know.
Vite is primarily a development server and build tool.
If you're building a React application, for example, you might have:
src/
├── App.tsx
├── main.tsx
└── components/
└── Button.tsx
You want to write code and immediately see the result in your browser.
That's where Vite comes in.
You can start your development server with:
vp dev
Under the hood, Vite is doing the work.
Why is Vite useful?
Imagine you change:
function Button() {
return <button>Hello</button>;
}
to:
function Button() {
return <button>Hello World</button>;
}
You don't want to stop the server, rebuild the entire application, and restart the browser every time you change a line.
Vite provides a fast development experience with features such as Hot Module Replacement (HMR).
In simple terms:
You change code
↓
Vite notices
↓
Browser updates
↓
You keep working
This is why Vite has become such a common part of modern frontend development.
With Vite+, you still get Vite.
Vite+ doesn't replace it.
2. Vitest — Testing
Writing code is only half of the job.
We also need to make sure it works.
That's where Vitest comes in.
Suppose you have this function:
function add(a: number, b: number) {
return a + b;
}
You could write a test:
import { expect, test } from "vitest";
test("adds two numbers", () => {
expect(add(2, 3)).toBe(5);
});
Then run:
vp test
Vite+ uses Vitest as its testing tool.
Why Vitest instead of something else?
You might already know tools such as Jest.
The important thing here isn't to decide which test runner is "the best."
The interesting part is that Vitest works very naturally with the Vite ecosystem.
That means your development and testing environments can share much of the same configuration and behavior.
Conceptually:
Development
↓
Vite
Testing
↓
Vitest
↓
Shared ecosystem
This integration is one of the reasons Vitest fits naturally into Vite+.
3. Rolldown — Bundling
Now we get to a term that can sound intimidating:
bundler.
Don't worry. The idea is simple.
Your application might contain hundreds or thousands of files:
src/
├── main.ts
├── App.tsx
├── components/
│ ├── Button.tsx
│ ├── Modal.tsx
│ └── Header.tsx
├── utils/
│ ├── date.ts
│ └── format.ts
└── ...
The browser doesn't necessarily need to receive all those files exactly as they exist in your source code.
A bundler analyzes the relationships between your files and produces optimized output for production.
Conceptually:
Your source code
↓
Bundler
↓
Production files
↓
Browser
Traditionally, Vite has used Rollup for production builds.
Vite+ includes Rolldown, a newer bundler written in Rust and designed to provide a high-performance bundling foundation for the Vite ecosystem.
You don't necessarily need to interact with Rolldown directly.
You can simply run:
vp build
and let the toolchain handle it.
Why does a bundler matter?
Imagine your application has:
10,000 lines of source code
You don't want to manually decide:
"Which files should be included?"
"Which modules depend on each other?"
"Can these files be combined?"
"Can unused code be removed?"
The bundler handles these kinds of problems.
It builds a dependency graph:
App
├── Header
├── Dashboard
│ ├── Chart
│ └── Table
└── Utils
Then it can produce optimized output.
This is one of the areas where build performance becomes important, especially for large projects.
4. tsdown — Building libraries
Applications aren't the only thing developers build.
Sometimes you're creating a library.
For example:
my-ui-library
my-auth-library
my-api-client
my-utils
Suppose you have:
export function formatDate(date: Date) {
// ...
}
You want other developers to install your package:
npm install my-utils
Now your build process has different requirements.
You may need:
- JavaScript output
- TypeScript declarations
- different module formats
- package metadata
- optimized output
This is where tsdown comes into the Vite+ ecosystem.
You can use:
vp pack
to package a library.
The important distinction is:
Application
↓
vp build
Library
↓
vp pack
The two workflows have different goals.
5. Oxlint — Linting
Now let's talk about code quality.
Imagine someone writes:
const user = getUser();
console.log(user);
if (user) {
// ...
}
The code might work.
But there may be problems:
- unused variables
- suspicious patterns
- accidental bugs
- inconsistent code
- practices your team doesn't allow
A linter looks for these kinds of issues.
Vite+ uses Oxlint for linting.
You can think of it as:
Your code
↓
Oxlint
↓
Potential problems
For example:
vp check
can include linting as part of the overall project check.
Why another linter?
You might be thinking:
"But we already have ESLint."
Yes.
ESLint is still widely used and has a huge ecosystem.
Oxlint takes a different approach and focuses heavily on performance.
It is part of the broader Oxc toolchain and is written in Rust.
For Vite+, the important idea is not:
"ESLint is bad."
It's:
"What if common development tooling could be extremely fast and integrated into one toolchain?"
That's the philosophy behind choosing tools such as Oxlint.
6. Oxfmt — Formatting
Linting and formatting are related, but they aren't the same thing.
A linter asks:
"Is there something potentially wrong with this code?"
A formatter asks:
"Can we make the code follow a consistent style?"
For example, these are functionally similar:
const user={name:"John"};
and:
const user = {
name: "John",
};
But most teams want everyone to use the same formatting rules.
That's where Oxfmt comes in.
You can think of it as the formatting part of the workflow:
Source code
↓
Oxfmt
↓
Consistent formatting
Again, this is similar to what developers have traditionally used Prettier for.
Linting vs formatting
If you're new to frontend development, this distinction is worth remembering.
Formatting
"Make the code look consistent."
Example:
const name="John"
becomes:
const name = "John";
Linting
"Look for patterns that might be problematic."
For example:
const unusedVariable = 123;
A linter can tell you:
unusedVariable is never used
So:
Oxfmt → How the code looks
Oxlint → Potential problems in the code
Both can be part of:
vp check
7. Vite Task — Running tasks
Now we get to a part that becomes more interesting as your project grows.
Most projects have tasks.
For example:
build
test
lint
typecheck
You might define them in package.json:
{
"scripts": {
"build": "...",
"test": "...",
"lint": "..."
}
}
For a small project, that's enough.
But imagine a monorepo with:
apps/
web/
admin/
packages/
ui/
auth/
utils/
Now tasks have relationships.
For example:
ui
↓
web
If the UI package changes, the web application may need to be rebuilt.
This is where a task runner becomes useful.
Vite+ includes Vite Task for task execution and caching.
Task dependencies
Let's make this concrete.
Imagine:
packages/ui
is used by:
apps/web
You change:
packages/ui/Button.tsx
The dependency graph is:
ui
↓
web
A smart task runner can understand:
"The web application depends on UI, so the web build may need to run."
But suppose another package didn't change:
packages/utils
If nothing relevant changed there, rebuilding everything may be unnecessary.
That's where task graphs and caching become useful.
Caching
Caching sounds complicated, but the basic idea is very simple.
Imagine you run:
vp run build
The build takes:
30 seconds
You run it again without changing anything.
Why should you spend another 30 seconds doing exactly the same work?
A cache can remember the previous result.
Conceptually:
First run:
Source
↓
Build
↓
Result
↓
Cache
Then:
Second run:
Source
↓
Anything relevant changed?
↓
No
↓
Reuse result
This becomes particularly valuable in large repositories and CI.
We'll go much deeper into this in Chapter 4.
8. Runtime and package management
There's another part of the developer experience that is easy to overlook:
the environment itself.
A project might expect:
Node.js 22
pnpm
while another project expects:
Node.js 20
npm
Vite+ also provides commands and workflows for managing the runtime and package manager environment.
For example:
vp env
can be used as part of this workflow.
The goal is to make the environment used by the project more explicit and reproducible.
This matters because:
"Works on my machine."
is one of the oldest problems in software development.
Putting the pieces together
Now we can see what sits behind the simple vp command.
Vite+
|
+------------------+------------------+
| | |
Development Quality Testing
| | |
Vite Oxlint + Oxfmt Vitest
|
Building
|
Rolldown
|
Libraries
|
tsdown
|
Tasks
|
Vite Task
Instead of learning every tool separately on day one, you can interact with them through a common workflow.
For example:
vp dev
→ development
vp test
→ testing
vp check
→ code quality
vp build
→ production build
vp pack
→ library packaging
vp run
→ project tasks
But should you care which tool is underneath?
Yes.
Even though Vite+ gives you a unified interface, you shouldn't treat it as magic.
If something goes wrong with your tests, knowing that Vite+ uses Vitest helps you investigate.
If your build has an issue, understanding Vite and Rolldown helps.
If linting reports something unexpected, knowing that Oxlint is involved gives you a direction for debugging.
This is especially important for senior developers.
A good abstraction hides unnecessary complexity.
It shouldn't hide useful knowledge.
The important mental model
Don't think:
Vite+ = one giant replacement for everything
Think:
Vite+ = an integrated workflow
↓
+-------+-------+
| | |
Vite Vitest Oxlint
| | |
Rolldown Tests Oxfmt
|
tsdown
|
Vite Task
Each component has a job.
Vite+ connects those components.
What we've learned
At this point, you don't need to remember every detail.
Just remember this:
| Tool | Simple explanation |
|---|---|
| Vite | Develop and build web applications |
| Vitest | Test your code |
| Rolldown | Bundle your application |
| tsdown | Package libraries |
| Oxlint | Find potential code problems |
| Oxfmt | Format your code |
| Vite Task | Run tasks and reuse cached results |
And Vite+ provides the common workflow around them.
One last question
Now that we know what's inside Vite+, there's still a practical question:
What does using it actually feel like?
It's one thing to read:
vp dev
vp test
vp check
vp build
It's another thing to create a project and use those commands yourself.
So in the next chapter, we'll stop talking about the pieces individually.
We'll build something.
We'll look at:
Create a project
↓
Install dependencies
↓
Start development
↓
Write code
↓
Run tests
↓
Check the project
↓
Build for production
That's where Vite+ starts becoming something you can actually use rather than just something you understand.
Next chapter: Vite+ in Practice — From Your First Project to Production
Top comments (0)