在第一章节里,我们看了 Vite+ 为什么存在。
简短的版本是:
现代 JavaScript 项目使用许多优秀的工具,但连接和维护所有这些工具可能会变得很复杂。
Vite+ 试图把其中几个工具整合到同一个工作流后面。
但这又引出了另一个问题:
Vite+ 里面到底有什么?
如果你看到:
vp dev vp test vp check vp build这些命令背后发生了什么?
让我们打开工具箱。
Vite+ 不是一个巨型工具
首先要理解的是,Vite+ 并不是对一切的单一替代品。
它把几个各司其职的工具整合到了一起。
一个简化视图是这样的:
Vite+ | +--------------+--------------+ | | | Development Quality Testing | | | Vite Oxlint / Oxfmt Vitest | Building | Rolldown +-----------------------------+ | Libraries | tsdown +-----------------------------+ | Tasks | Vite Task每个工具解决不同的问题。
重要的是,Vite+ 给了你一个一致的方式与它们协作。
让我们逐个过一遍。
1. Vite — 开发
先从大多数开发者已经知道的工具开始。
Vite主要是一个开发服务器和构建工具。
例如,如果你在构建一个 React 应用,你可能有:
src/ ├── App.tsx ├── main.tsx └── components/ └── Button.tsx你想写代码并立即在浏览器里看到结果。
这就是 Vite 发挥作用的地方。
你可以用下面命令启动开发服务器:
vp dev在背后,是 Vite 在做这些工作。
为什么 Vite 有用?
想象你把:
function Button() { return <button>Hello</button>; }改成:
function Button() { return <button>Hello World</button>; }你不想每次改一行代码就停服务器、重建整个应用、重启浏览器。
Vite 通过诸如热模块替换(HMR)之类的特性提供了快速的开发体验。
简单来说:
你改代码 ↓ Vite 注意到 ↓ 浏览器更新 ↓ 你继续工作这就是为什么 Vite 已成为现代前端开发中如此常见的一部分。
使用 Vite+,你仍然得到 Vite。
Vite+ 不会替换它。
2. Vitest — 测试
写代码只完成了一半的工作。
我们还需要确保它能正常工作。
这就是Vitest发挥作用的地方。
假设你有这个函数:
function add(a: number, b: number) { return a + b; }你可以写一个测试:
import { expect, test } from "vitest"; test("adds two numbers", () => { expect(add(2, 3)).toBe(5); });然后运行:
vp testVite+ 使用 Vitest 作为它的测试工具。
为什么用 Vitest 而不是别的?
你可能已经知道 Jest 之类的工具。
这里重要的不是决定哪个测试运行器"最好"。
有意思的是,Vitest 与 Vite 生态协作得非常自然。
这意味着你的开发和测试环境可以共享很多相同的配置和行为。
概念上:
Development ↓ Vite Testing ↓ Vitest ↓ Shared ecosystem这种整合是 Vitest 自然融入 Vite+ 的原因之一。
3. Rolldown — 打包
现在我们要接触一个可能听起来吓人的术语:
bundler(打包器)。
别担心。这个想法很简单。
你的应用可能包含成百上千个文件:
src/ ├── main.ts ├── App.tsx ├── components/ │ ├── Button.tsx │ ├── Modal.tsx │ └── Header.tsx ├── utils/ │ ├── date.ts │ └── format.ts └── ...浏览器不一定需要原样接收你源代码里存在的所有文件。
打包器分析你文件之间的关系,并为生产环境生成优化后的输出。
概念上:
你的源代码 ↓ Bundler ↓ 生产文件 ↓ Browser传统上,Vite 使用 Rollup 进行生产构建。
Vite+ 包含Rolldown——一个用 Rust 编写的新打包器,旨在为 Vite 生态提供高性能的打包基础。
你不一定需要直接与 Rolldown 交互。
你只需运行:
vp build让工具链处理一切。
为什么打包器重要?
想象你的应用有:
10,000 行源代码你不想手动决定:
"应该包含哪些文件?"
"哪些模块互相依赖?"
"这些文件可以合并吗?"
"可以移除未使用的代码吗?"
打包器处理这类问题。
它构建一个依赖图:
App ├── Header ├── Dashboard │ ├── Chart │ └── Table └── Utils然后它可以生成优化后的输出。
这是构建性能变得重要的领域之一,尤其对大型项目。
4. tsdown — 构建库
应用不是开发者构建的唯一东西。
有时你在创建库。
例如:
my-ui-library my-auth-library my-api-client my-utils假设你有:
export function formatDate(date: Date) { // ... }你想让其他开发者安装你的包:
npm install my-utils现在你的构建过程有了不同的需求。
你可能需要:
- JavaScript 输出
- TypeScript 声明
- 不同的模块格式
- 包元数据
- 优化后的输出
这就是tsdown进入 Vite+ 生态的地方。
你可以使用:
vp pack来打包一个库。
重要的区别是:
Application ↓ vp build Library ↓ vp pack这两个工作流有不同的目标。
5. Oxlint — 代码检查
现在让我们谈谈代码质量。
想象有人写了:
const user = getUser(); console.log(user); if (user) { // ... }代码可能能工作。
但可能有这些问题:
- 未使用的变量
- 可疑的模式
- 意外的 bug
- 不一致的代码
- 你的团队不允许的实践
linter(代码检查器)会查找这类问题。
Vite+ 使用Oxlint做代码检查。
你可以这样理解:
你的代码 ↓ Oxlint ↓ 潜在问题例如:
vp check可以把 lint 作为整个项目检查的一部分。
为什么又一个 linter?
你可能会想:
"但我们已经有了 ESLint。"
是的。
ESLint 仍被广泛使用,而且有巨大的生态。
Oxlint 采取了不同的方法,高度专注于性能。
它是更广泛的Oxc工具链的一部分,用 Rust 编写。
对 Vite+ 来说,重要的想法不是:
"ESLint 很糟糕。"
而是:
"如果常见的开发工具能极其快速,并整合到同一个工具链里呢?"
这就是选择 Oxlint 这类工具背后的哲学。
6. Oxfmt — 格式化
代码检查和格式化相关,但它们是两回事。
linter 问的是:
"这段代码可能有哪里不对?"
格式化工具问的是:
"我们能把这些代码变成一致的风格吗?"
例如,这些在功能上是相似的:
const user={name:"John"};和:
const user = { name: "John", };但大多数团队希望每个人都使用相同的格式化规则。
这就是Oxfmt发挥作用的地方。
你可以把它想成工作流中负责格式化的部分:
源代码 ↓ Oxfmt ↓ 一致的格式同样,这类似于开发者传统上使用 Prettier 做的事情。
代码检查 vs 格式化
如果你刚接触前端开发,这个区别值得记住。
格式化
"让代码看起来一致。"
例如:
const name="John"变成:
const name = "John";代码检查
"查找可能有问题的模式。"
例如:
const unusedVariable = 123;一个 linter 会告诉你:
unusedVariable 从未被使用所以:
Oxfmt → 代码看起来什么样 Oxlint → 代码里有什么潜在问题两者都可以是:
vp check的一部分。
7. Vite Task — 运行任务
现在我们要接触一个随着项目增长而变得更有意思的部分。
大多数项目都有任务。
例如:
build test lint typecheck你可能在package.json里定义它们:
{ "scripts": { "build": "...", "test": "...", "lint": "..." } }对小项目来说,这足够了。
但想象一个 monorepo 有:
apps/ web/ admin/ packages/ ui/ auth/ utils/现在任务之间有了关系。
例如:
ui ↓ web如果 UI 包变了,web 应用可能需要重新构建。
这就是任务运行器变得有用的地方。
Vite+ 包含Vite Task用于任务执行和缓存。
任务依赖
让我们把这个具体化。
想象:
packages/ui被:
apps/web使用。
你改了:
packages/ui/Button.tsx依赖图是:
ui ↓ web一个智能的任务运行器能理解:
"web 应用依赖 UI,所以 web 构建可能需要运行。"
但假设另一个包没有变:
packages/utils如果那里没有相关变化,重建一切可能是不必要的。
这就是任务图和缓存变得有用的地方。
缓存
缓存听起来复杂,但基本想法非常简单。
想象你运行:
vp run build构建花了:
30 秒你在什么都没改的情况下又运行了一次。
为什么还要再花 30 秒做完全相同的工作?
缓存可以记住之前的结果。
概念上:
第一次运行: Source ↓ Build ↓ Result ↓ Cache然后:
第二次运行: Source ↓ 有什么相关的东西变了吗? ↓ 没有 ↓ 复用结果这在大型仓库和 CI 中变得特别有价值。
我们会在第四章深入探讨这一点。
8. 运行时和包管理
开发者体验还有另一个容易被忽视的部分:
环境本身。
一个项目可能期望:
Node.js 22 pnpm而另一个项目期望:
Node.js 20 npmVite+ 也提供用于管理运行时和包管理器环境的命令和工作流。
例如:
vp env可以作为这个工作流的一部分。
目标是让项目使用的环境更明确、更可复现。
这很重要,因为:
"在我机器上能跑。"
是软件开发里最古老的问题之一。
把各部分拼起来
现在我们可以看清简单的vp命令背后是什么了。
Vite+ | +------------------+------------------+ | | | Development Quality Testing | | | Vite Oxlint + Oxfmt Vitest | Building | Rolldown | Libraries | tsdown | Tasks | Vite Task与其第一天就单独学习每个工具,你可以通过一个通用的工作流与它们交互。
例如:
vp dev→ 开发
vp test→ 测试
vp check→ 代码质量
vp build→ 生产构建
vp pack→ 库打包
vp run→ 项目任务
但你应该关心底下是哪个工具吗?
是的。
即使 Vite+ 给你一个统一的界面,你也不应该把它当作魔法。
如果你的测试出了问题,知道 Vite+ 使用 Vitest 能帮助你排查。
如果你的构建有问题,理解 Vite 和 Rolldown 会有帮助。
如果 lint 报告了意外的东西,知道涉及 Oxlint 会给你一个调试方向。
这对资深开发者尤其重要。
好的抽象隐藏了不必要的复杂性。
它不应该隐藏有用的知识。
重要的心智模型
不要想:
Vite+ = 对一切的一个巨型替代品要想:
Vite+ = 一个整合的工作流 ↓ +-------+-------+ | | | Vite Vitest Oxlint | | | Rolldown Tests Oxfmt | tsdown | Vite Task每个组件都有工作要做。
Vite+ 连接这些组件。
我们学到了什么
在这一点上,你不需要记住每个细节。
只需记住这个:
| 工具 | 简单解释 |
|---|---|
| Vite | 开发和构建 Web 应用 |
| Vitest | 测试你的代码 |
| Rolldown | 打包你的应用 |
| tsdown | 打包库 |
| Oxlint | 发现潜在的代码问题 |
| Oxfmt | 格式化你的代码 |
| Vite Task | 运行任务并复用缓存结果 |
而 Vite+ 提供了围绕它们的通用工作流。
最后一个问题
既然我们知道了 Vite+ 里面有什么,还有一个实际问题:
实际使用它是什么感觉?
读:
vp dev vp test vp check vp build是一回事。
创建项目并使用这些命令是另一回事。
所以在下一章,我们将不再单独谈论这些部分。
我们将构建一些东西。
我们将看到:
创建项目 ↓ 安装依赖 ↓ 开始开发 ↓ 写代码 ↓ 运行测试 ↓ 检查项目 ↓ 生产构建这就是 Vite+ 开始变成你可以真正使用的东西,而不仅仅是你理解的东西。
下一章:Vite+ 实战——从你的第一个项目到生产环境
如果你也对前端工具链感兴趣,欢迎参考本站的浏览器卡顿排查和更多实用教程。
相关阅读:
- 如何让 iPhone Safari 在后台打开新标签页
- 如何在 Safari 浏览器中允许或拦截弹窗
- Windows 网络连接相关设置教程