ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Vite+ — 第二章:Vite+ 里面到底有什么?

Vite+ — 第二章:Vite+ 里面到底有什么? 在第一章节里我们看了 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 buttonHello/button; }改成function Button() { return buttonHello 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 nameJohn变成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 网络连接相关设置教程
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进