Vite 学习总结:核心知识体系回顾

10 min中级

串联模块十二篇文档:从原生 ESM 与依赖预构建到配置、HMR、代码分割、插件系统与 Vite 8 Rolldown 单引擎的完整知识体系回顾。

本篇是 vite 模块的收官总结。我们假设你在为”虚拟歌手音乐平台”搭建前端:站点要展示歌姬的应援色主题页、P 主的作品列表和演唱会开票倒计时。围绕这些场景,把前 12 篇文档的内容重新串一遍——开发时为什么快、资源与样式怎么走、构建产物怎么切、插件如何扩展,以及 Vite 8 的 Rolldown 单引擎意味着什么。读完请用自检清单核对掌握程度。回顾时建议自问自答:每看到一项配置,先合上文档问自己”不配会发生什么”,再展开验证。Vite 的知识分为开发期、构建期与扩展期三块,彼此独立又互相衔接,卡在哪一块就回哪一篇精读,不必从头再来。

前置知识

  • Vite 构建工具概述:原生 ESM 与依赖预构建是理解一切后续机制的前提,总结前请先回顾”快递分拣中心”类比。
  • Vite 快速上手与项目结构:dev/build/preview 三个命令与目录结构是动手操作的基础,本文所有示例都基于该结构。

学习目标

  1. 能解释 Vite 开发时”按需请求 + 依赖预构建”与生产时”整包构建”的两套工作模式差异。
  2. 能独立编写 vite.config.ts,覆盖路径别名、开发代理、构建分包与环境变量等高频配置项。
  3. 能为静态资源选对存放位置(public 还是 src/assets),并说清两条路径在构建期分别发生什么。
  4. 能编写简单的自定义插件,理解 Rolldown 单引擎对插件生态与开发构建一致性的影响。

知识地图

flowchart TD
  subgraph intro["入门认知"]
    A["001 构建工具概述"]
    B["002 快速上手与项目结构"]
  end
  subgraph config["配置与环境"]
    C["003 配置文件详解"]
    D["010 环境变量与模式"]
  end
  subgraph assets["资源与样式"]
    E["004 静态资源处理"]
    F["005 CSS 与预处理器"]
  end
  subgraph devbuild["开发与构建"]
    G["006 开发服务器与 HMR"]
    H["007 生产构建与代码分割"]
  end
  subgraph extend["扩展与演进"]
    I["008 插件系统"]
    J["009 Vite 8 与 Rolldown"]
  end
  subgraph advanced["进阶方向"]
    K["011 服务端渲染 SSR"]
    L["012 Vitest 测试集成"]
  end
  A --> B
  B --> C
  C --> D
  C --> E
  E --> F
  F --> G
  C --> H
  H --> I
  I --> J
  J --> K
  J --> L

读图按编号推进即可:001、002 打底,003 与 010 管配置,004 与 005 管资源与样式,006 管开发体验,007 与 009 管构建与引擎,008 管扩展能力,011、012 是两个待补全的进阶方向。箭头大致就是依赖关系:不理解配置,资源与代理的讨论就悬在半空;不理解构建,插件的学习也会缺一个挂靠点。

核心概念回顾

1. 为什么快:原生 ESM 与依赖预构建

传统打包器开发时要先把整个项目打成一个大 bundle;Vite 则让浏览器按需向开发服务器请求模块,改一行代码只处理一个文件。但第三方依赖动辄几百个模块请求,所以 Vite 在首次启动时用引擎把它们预构建成单文件缓存起来——这就是”冷启动一次、之后毫秒级”的原因(见构建工具概述)。平台入口对歌姬主页的按需引用就是这条链路:

<!-- index.html:浏览器直接请求 main.ts,开发服务器逐个转换返回 -->
<body>
  <script type="module" src="/src/main.ts"></script>
</body>
// src/main.ts —— 只有当前页面用到的模块才会被请求与转换
import { renderSingerPage } from "./pages/singer"
import { themeColor } from "./config/theme" // 应援色配置,独立小模块

renderSingerPage(themeColor.miku) // 按需引入,改 theme 不必重启应用

依赖预构建做两件事:把几百个零散的依赖模块合并成单文件减少请求数,把 CommonJS 依赖转换成 ESM 以便浏览器直接消费。缓存位于 node_modules/.vite,只有 lockfile 或相关配置变化才会失效——开发服务器突然变慢时,先想想最近是不是动过依赖,而不是急着重启。

2. 配置文件:方向盘与仪表盘

vite.config.ts 决定端口、别名、代理、插件与构建产物形态,defineConfig 提供完整类型提示。音乐平台最典型的两处配置是 @ 别名与 /api 代理——前端请求转发给后端歌曲服务(见配置文件详解):

// vite.config.ts —— 平台前端的核心配置
import { defineConfig } from "vite"

export default defineConfig({
  resolve: {
    alias: { "@": "/src" } // 统一用 @ 指向 src,深层导入不再写长相对路径
  },
  server: {
    proxy: {
      // 歌曲与演唱会接口转发给后端,避免开发期跨域
      "/api": { target: "http://localhost:3000", changeOrigin: true }
    }
  }
})

配置文件按 vite.config.ts、mjs、js 的优先级自动加载,还能按 mode 差异化环境。写配置时牢记”不配、配、配好”的三段对比:每一项配置都应能回答”不配会怎样”,回答不了的就删掉——配置膨胀同样是需要偿还的技术债,精简的配置文件本身就是团队文档。

3. 静态资源:两类货架

静态资源分两种存放方式:src/ 下的资源用 import 引入,参与构建(加内容哈希、可压缩、可内联);public/ 下的资源原样复制,适合favicon、robots.txt 这类不需要处理的文件(见静态资源处理):

// src/pages/singer.ts —— 歌姬立绘走"加工区",构建后获得哈希文件名
import singerCover from "@/assets/singer-cover.svg" // 参与 hash 与压缩
import themeSheet from "@/assets/theme-colors.json" // 应援色表也能 import

export function renderSingerPage(color: string) {
  document.querySelector<HTMLImageElement>("#cover")!.src = singerCover
  document.body.style.setProperty("--theme-color", color) // CSS 变量换肤
  void themeSheet
}

CSS Modules 的价值在多人协作时最明显:平台前端两位开发者各自的 .card 互不干扰,类名经编译后带哈希;若项目不需要局部化,普通 import 同样会走 PostCSS 流水线,获得厂商前缀补全与压缩。理解这条流水线后,样式问题的排查就有章可循:先定位是哪一站出了问题。

4. CSS 流水线:从 Sass 到浏览器

一段 Sass 源码要经过”入口登记、预处理器编译、PostCSS 后处理、CSS Modules 局部化、注入或抽取”五站才能生效。开发时以 <style> 标签注入保证 HMR 粒度,生产时抽取为独立 CSS 按需加载(见CSS 与预处理器):

/* src/pages/singer.module.css —— CSS Modules:类名自动局部化,不怕冲突 */
.card {
  border-left: 4px solid var(--theme-color); /* 应援色竖条,直角小圆角 */
  padding: 12px 16px;
}

.cardTitle {
  font-size: 1.125rem;
}
// 组件侧按模块导入样式对象,编译期完成类名映射
import styles from "./singer.module.css"

document.querySelector("#song-card")!.className = styles.card

HMR 的边界决定开发体验:CSS 与框架组件有现成的热替换边界,自定义模块要靠 import.meta.hot.accept 显式接住;边界之外的改动(例如修改配置文件)只能整页重启。知道哪些改动会越界、哪些能就地替换,比记住 API 本身更重要。

5. 开发服务器与 HMR

HMR 的本质是”模块图 + WebSocket”:服务器监听文件变化,沿模块图找出受影响的边界,把最新模块推给浏览器就地替换,页面状态不丢失。Vite 对 CSS、Vue、React 提供开箱即用的热替换,原生模块可用 import.meta.hot 自定义(见开发服务器与 HMR):

// src/config/theme.ts —— 应援色配置热更新:改配置不用整页刷新
export const themeColor = { miku: "#39c5bb", teto: "#eba9ee" }

if (import.meta.hot) {
  // 接受自身更新,并把最新应援色同步给已渲染的页面
  import.meta.hot.accept((newModule) => {
    document.body.style.setProperty("--theme-color", newModule!.themeColor.miku)
  })
}

分包策略的核心是按变化频率分组:业务代码高频变化,第三方依赖低频变化,拆开后业务迭代不会击穿依赖包的浏览器缓存。优化结果应当用产物分析工具量化验证,而不是凭感觉下结论——《Vite 生产构建与代码分割》篇的事故现场就是从 Network 面板与构建输出开始定位的。

6. 生产构建与代码分割

构建期的核心是”首屏只带必需代码”:路由懒加载把非首页切成独立 chunk,manualChunks 把稳定的大依赖单独分包以利用缓存,tree-shaking 顺带删掉没用到的导出。平台把演唱会压轴的重依赖单独拆包(见生产构建与代码分割):

// src/router.ts —— 演唱会页懒加载:进入路由才下载对应 chunk
const routes = [
  { path: "/singers", component: () => import("./pages/singers") },
  { path: "/concerts", component: () => import("./pages/concerts") } // 开票页重逻辑
]
// vite.config.ts 构建片段 —— 播放器大依赖单独成包,业务更新不影响其缓存
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: { player: ["hls.js"] } // 演唱会直播播放器独立分包
      }
    }
  }
})

插件的本质是”带钩子的对象”:resolveId 负责把导入解析成模块 id,load 决定源码从哪里来,transform 对源码加工,钩子返回 null 表示放行给下一个处理者。这一约定让插件像流水线工位一样自由组合,社区生态的”插口标准”也由此保持稳定。

7. 插件系统与 Vite 8 Rolldown

插件是带名字与钩子函数的对象:resolveId、load、transform 等钩子在模块解析链上各司其职,社区生态由此生长。Vite 8 用 Rust 写的 Rolldown 取代了”开发 esbuild + 生产 Rollup”的双引擎架构,开发与生产行为一致,兼容既有 Rollup 插件 API(见插件系统与Vite 8 与 Rolldown 新特性):

// vite.config.ts —— 自定义插件:把应援色标记编译成主题变量
function singerThemePlugin(): Plugin {
  return {
    name: "singer-theme",
    // transform 钩子逐模块过滤并改写源码
    transform(code, id) {
      if (!id.endsWith(".theme.ts")) return null // 不匹配则跳过
      return code.replaceAll("THEME_COLOR", "#39c5bb")
    }
  }
}

Rolldown 单引擎最大的红利是开发与生产共享同一套行为:过去在开发服务器验证过的代码,到生产构建才发现兼容问题的时代结束了。现有插件大多无需改动即可兼容,迁移时重点做一次生产构建产物的前后对比,确认 chunk 划分与资源路径没有意外变化。

易混淆概念对比

静态资源放哪里最常被纠结,本质是”要不要参与构建”:

维度src/assets(import 引入)public/(原样复制)
是否参与构建是:哈希命名、压缩、可内联否:按原文件名直接复制
引用方式import cover from "./a.svg"/a.svg 根路径字符串
适用资源歌姬立绘、应援色图、字体favicon、robots.txt、第三方固定脚本
改动影响文件名变化,引用自动更新需自行处理缓存版本

另一组关键对比是 Vite 8 前后的引擎架构,它解释了许多”开发正常、上线报错”的旧问题为何消失:

维度Vite 7 及之前(双引擎)Vite 8(Rolldown 单引擎)
开发期依赖/转换esbuildRolldown(Oxc 系)
生产构建RollupRolldown
行为一致性两引擎行为有差异,切换处易出问题一套引擎,开发与生产结果一致
插件生态Rollup 插件 API兼容 Rollup 插件 API,平滑迁移

常见误区与排查

以下五条是社区与实战里最常见的翻车姿势,每条先给错误写法,再给修正代码。

  1. 需要构建处理的图片放进了 public/,结果既没有哈希也没有压缩,还引用不到。应移入 src/assets 并用 import 引入:
// 错误:public 下的文件不参与构建,无 hash 无压缩
// const cover = "/assets/singer-cover.svg"

// 正确:import 引入,构建后自动获得内容哈希文件名
import cover from "@/assets/singer-cover.svg"
  1. 客户端想读的环境变量没加 VITE_ 前缀,import.meta.env 里永远是 undefined。变量名决定暴露范围(环境变量与模式是模块规划主题之一):
// 错误:没加前缀,不会暴露给客户端代码
// const api = import.meta.env.API_BASE

// 正确:VITE_ 前缀的变量才会进入 import.meta.env
const api = import.meta.env.VITE_API_BASE // 例如 "/api"
  1. 部署到子路径后页面白屏、资源 404,因为构建时 base 仍是默认的 /。按实际部署路径配置:
// vite.config.ts —— 平台部署在 /fandex/ 子路径下
export default defineConfig({
  base: "/fandex/" // 所有资源引用都会带上该前缀
})
  1. 用变量拼接动态导入路径,构建器无法静态分析,打包出整个目录甚至失败。动态 import 必须给出可分析的字符串字面量起点:
// 错误:完全动态的路径无法被静态分析
// const page = await import(`./pages/${name}.ts`)

// 正确:写死目录前缀,构建器为目录下每个模块生成对应 chunk
const page = await import(`./pages/${name}/index.ts`)
  1. 开发代理配了 pathRewrite(webpack 的字段),Vite 并不认识。Vite 的代理基于 http-proxy,改写路径要用 rewrite 函数:
// vite.config.ts —— 代理时去掉 /api 前缀再转发给歌曲服务
server: {
  proxy: {
    "/api": {
      target: "http://localhost:3000",
      changeOrigin: true,
      rewrite: (path) => path.replace(/^\/api/, "")
    }
  }
}

自检清单

  • 能解释”浏览器按需请求模块”与”依赖预构建”分别解决了什么问题
  • 能在 vite.config.ts 中独立完成别名、代理与端口配置,并说出每项的作用
  • 面对一个新图片资源,能立刻判断该放 public/ 还是 src/assets 并说明理由
  • 能说出 CSS 从 Sass 源码到浏览器生效要经过的流水线各站
  • 能用 import.meta.hot 写出自定义模块的热更新接受逻辑
  • 能用路由懒加载与 manualChunks 把首屏 JS 体积压下来,并用产物分析验证
  • 能写出一个至少含 transform 钩子的自定义插件
  • 能说出 Vite 8 的 Rolldown 单引擎改变了什么、为什么兼容旧插件

总结的意义不在覆盖全部细节,而在需要时知道去哪找:开发服务器变慢查 001 与 006,包体积超标查 007,开发与生产行为不一致查 009,样式问题查 005,想写插件查 008。把这份”问题到文档”的映射留在脑子里,比背诵任何一段配置都有用。

后续学习路径

  1. 补齐配置细节:精读配置文件详解的”不配、配、配好”三段对比,把每一项为什么存在讲给自己听。
  2. 深入开发体验:按开发服务器与 HMR复现模块图与热替换边界的实验。
  3. 优化生产产物:跟随生产构建与代码分割从事故现场走一遍优化链路,再读插件系统尝试动手写插件。
  4. 展望架构演进:阅读Vite 8 与 Rolldown 新特性理解单引擎时代,并关注环境变量与模式、服务端渲染 SSR、Vitest 测试集成的后续更新。