Vite 3.0 发布解析:冷启动优化、import.meta.glob 重写与 ESM SSR 构建革新
Vite 3.0 是 Vite 团队在 v2 发布 16 个月后推出的年度大版本,这篇技术文章基于官方发布公告 announcing-vite3.md,完整梳理 v3 的发布背景与全部技术变更:开发体验升级(CLI、默认端口 5173/4173、WebSocket 连接策略、冷启动免重载优化)、import.meta.glob 的全面重写、WASM 导入 API 对齐、SSR 构建默认 ESM、相对 base 支持、三个实验性特性,以及 30% 的包体积缩减与 Node.js/浏览器兼容性基线调整。读完本文,你将掌握 Vite 3 每项变更的动机与用法,并能在当前仓库源码中找到这些特性的对应实现,理解它们如何从“发布时的承诺”演化为今天 Vite 的核心能力。
一、发布背景:Vite 2 之后的生态扩张
公告开篇回顾了 Vite 2(2021 年 2 月由 Evan You 发布)到 Vite 3 之间 16 个月的生态变化:npm 周下载量突破 100 万,一个快速扩张的生态体系随之形成——Nuxt 3 默认使用 Vite,SvelteKit、Astro、Hydrogen、SolidStart 等框架均构建于 Vite 之上,Laravel 9 也决定默认接入 Vite。公告还提到这些生态项目的维护者反过来深度参与 Vite 核心开发,与 Vite 团队(见 team.md)和众多贡献者协同推进。
基于这种生态节奏,团队做出了一项明确的版本策略决策:
至少每年发布一个 Vite 大版本,以对齐 Node.js 的 EOL(生命周期结束)节奏,并借大版本之机定期审视 Vite 的 API,为生态项目保留一条较短的迁移路径。
这一策略贯穿了后续 Vite 4、Vite 5……直至当前仓库所处的版本(packages/vite/package.json 中 version 字段显示为 8.2.2)。从源码结构看,当年公告中承诺的“短迁移路径”确实被执行:v3 中的多个实验特性(如 esbuild 构建期依赖优化)最终在后续版本中转正或替代,而 HMR 部分接受(Partial Accept)等能力则沉淀进了 HMR 核心。
二、全新文档站点与模板主题
Vite 3 同步发布了新版文档:
- 文档迁移到 VitePress 默认主题,带来出色的暗色模式体验;
- Vite 2 的旧文档继续保留在线,另有
main.vite.dev子域名,Vite 主分支的每个 commit 都会自动部署,方便在测试 beta 版或参与核心开发时查阅最新文档; - 官方文档新增西班牙语翻译,与已有的简体中文、日文并列。
仓库中的 blog.md 与 docs/_data/blog.data.ts 负责将本博客(含本文对应的公告)渲染到文档站上。
Create Vite 启动模板
create-vite 的模板在 Vite 3 中统一更换了与新文档一致的主题,以传达这些模板“最小化起步”的定位——更完整的 lint、测试配置等方案由框架方的官方模板提供。当前仓库中的 packages/create-vite/ 保留了这一设计脉络:每个框架一套极简模板目录,包括:
- template-vue/ 与 template-vue-ts/
- template-react/ 与 template-react-ts/
- template-svelte/、template-lit/、template-preact/、template-solid/、template-qwik/
- 纯语言的 template-vanilla/ 与 template-vanilla-ts/
模板的解析逻辑在 packages/create-vite/src/create.ts 中,模板清单的快照测试见 packages/create-vite/tests/create.test.ts。
三、开发体验改进
3.1 CLI 与新默认端口
Vite 3 的 CLI 输出做了美化,更重要的是默认端口变更:
VITE v3.0.0 ready in 320 ms
➜ Local: http://127.0.0.1:5173/
➜ Network: use --host to expose
- 开发服务器默认端口改为 5173
- 预览服务器(
vite preview)监听 4173
选择 5173 是为了避开与其他工具的端口冲突。在当前仓库中,这两个端口被固化为常量:
- packages/vite/src/node/constants.ts:
export const DEFAULT_DEV_PORT = 5173与export const DEFAULT_PREVIEW_PORT = 4173
CLI 输出格式也有对应的测试保障:packages/vite/src/node/tests/logger.spec.ts 及其快照 logger.spec.ts.snap 验证了 Local:/Network: 行的渲染结果,Network 行在 --host 未开启时的 “use --host to expose” 提示与公告截图一致。
3.2 改进的 WebSocket 连接策略
Vite 2 时代的一个痛点是代理后面的服务器配置:当应用跑在反向代理之后时,HMR 的 WebSocket 连接经常无法直连。Vite 3 改变了默认连接方案,使其在大多数场景下开箱即用;这些代理部署场景(如 vite-setup-catalogue 收录的各类部署组合)被纳入生态 CI 持续测试。从当前源码结构看,这一策略演化为 server.hmr.clientPort / protocol 等配置项以及客户端对连接地址的协商逻辑(相关配置说明见 docs/config/server-options.md)。
3.3 冷启动优化:优化依赖不再触发整页重载
这是 Vite 3 开发体验上最重要的改进之一:当插件在爬取初始静态依赖的过程中注入新的 import 时,Vite 不再触发整页重载。公告原文给出了 v2.9 与 v3 策略的对比:
- Vite 2.9:scanner 和 optimizer 都在后台运行。最佳情况下(scanner 找齐所有依赖)冷启动无需重载;但若 scanner 漏掉依赖,就会触发新一轮优化并需要整页重载。v2.9 曾通过检测“新优化产物是否与浏览器已有的兼容”来避免部分重载,但只要存在公共依赖导致子 chunk 变化,就仍需重载以避免重复状态;
- Vite 3:优化后的依赖在静态 import 爬取完成之前不会交给浏览器。如果爬取后发现遗漏的依赖(例如由插件注入),Vite 只执行一次快速的补充优化,然后把完整的依赖产物一次性发给浏览器——因此这类场景不再需要页面重载。
当前仓库中,该机制的对应实现集中在依赖优化与模块爬取两条链路上:vite:optimized-deps 插件(packages/vite/src/node/plugins/optimizedDeps.ts)与 importAnalysis 插件(packages/vite/src/node/plugins/importAnalysis.ts)负责在发现缺失依赖时触发再优化并将浏览器侧请求重新指向优化产物,相关行为由 playground/optimize-deps/ 系列 E2E 用例(playground/optimize-deps/)持续验证。
3.4 import.meta.glob 全面重写
import.meta.glob 的底层支持在 Vite 3 中被重写,新增了五项能力(公告给出的完整示例):
1. 多模式(Multiple Patterns)——以数组形式传入多个 glob:
import.meta.glob(['./dir/*.js', './another/*.js'])
2. 负向模式(Negative Patterns)——以 ! 前缀忽略特定文件:
import.meta.glob(['./dir/*.js', '!**/bar.js'])
3. 命名导入(Named Imports)——指定默认导入的绑定名,利于 tree-shaking:
import.meta.glob('./dir/*.js', { import: 'setup' })
4. 自定义查询(Custom Queries)——附加元数据:
import.meta.glob('./dir/*.js', { query: { custom: 'data' } })
5. Eager 改为选项标志:
import.meta.glob('./dir/*.js', { eager: true })
这些用法在当前文档 docs/guide/features.md 的 “Glob Import” 一节中有完整保留(Multiple Patterns、Named Imports、Custom Queries 等小节)。
源码层面的印证同样清晰。glob 插件 packages/vite/src/node/plugins/importMetaGlob.ts 在 transform 中解析 import.meta.glob 调用,其选项类型 GeneralImportGlobOptions 定义于 packages/vite/src/types/importGlob.d.ts;插件将解析出的 glob 拆分为肯定(affirmed)与否定(negated)两组,用 picomatch 编译成匹配器:
// importMetaGlob.ts 中的匹配语义:(glob1 || glob2) && !(glob3 || glob4)
(affirmed.length === 0 || affirmedMatcher(file)) &&
!(negated.length > 0 && negatedMatcher(file))
值得注意的是该插件还注册了 hotUpdate 钩子:当 glob 命中的文件集合发生变化(新增/删除文件)时,能主动失效引用了该 glob 的模块——这是 glob 导入参与 HMR 的机制,对应行为可用 playground/glob-import/ 目录下的用例(含 playground/glob-import/root/ 的 27 个测试文件)复现验证。
3.5 WASM 导入 API 对齐未来标准
Vite 3 修订了 WebAssembly 导入 API,避免与未来标准(如 WASM ESM 集成提案)冲突,并变得更灵活——通过 ?init 查询后缀显式触发初始化:
import init from './example.wasm?init'
init().then((instance) => {
instance.exports.test()
})
这一 API 在当前仓库中仍然生效。packages/vite/src/node/plugins/wasm.ts 中的正则即按该后缀识别:const wasmInitRE = /(?<![?#].*)\.wasm\?init/,同文件还处理直接 .wasm 导入(对应 WASM ESM Integration)与 MIME 类型不匹配时退化为 WebAssembly.instantiate 的逻辑。完整的用法说明见 docs/guide/features.md 的 WebAssembly 小节,端到端测试位于 playground/wasm/(含多个 .wasm 二进制与 TS 用例)。
四、构建改进
4.1 SSR 构建默认输出 ESM
生态中大多数 SSR 框架(Nuxt 3、SvelteKit、Astro 等)早已在使用 ESM 产物,因此 Vite 3 将 ESM 设为 SSR 构建的默认格式。这直接简化了此前的 SSR 依赖外部化(externalization)启发式规则:依赖默认被外部化,不再需要为 CJS/ESM 双格式做复杂判断。
当前文档 docs/guide/ssr.md 的 “SSR Externals” 一节仍然描述这一行为:“Dependencies are externalized from Vite's SSR transform module system by default when running SSR”,并说明链接(linked)依赖默认不外部化以利用 HMR,可通过 ssr.external 调整(配置项定义见 docs/config/ssr-options.md)。外部化决策的核心实现可从 packages/vite/src/node/ssr/ssrExternal.ts 一带的源码追起,playground/ssr-deps/ 中 29 个 JS/JSON 用例覆盖了各种依赖形态下的外部化行为。
4.2 相对 base 支持
Vite 3 正确支持了相对 base(base: ''),使构建产物可以在不同 base 路径下部署而无需重新构建。典型场景是构建期未知 base 的内容寻址网络(如 IPFS)。仓库中这一能力有直接的配置示例佐证:playground/assets/vite.config-relative-base.js 即使用相对 base 运行资产 URL 相关的全部 E2E 用例。
五、实验性特性
Vite 3 同时以实验(Experimental)身份引入了三项特性,公告明确说明它们为生态留出了消化时间:
5.1 构建产物路径的细粒度控制(Experimental)
针对“带 hash 的产物需要部署到与 public 文件不同的 CDN”等场景,Vite 3 提供了在构建期修改产物路径的实验 API(build.rollupOptions.output 中的 entryFileNames/chunkFileNames 等高级 base 选项,说明见 docs/guide/build 相关配置文档),用于相对 base 无法满足的更细粒度部署需求。
5.2 构建期使用 esbuild 优化依赖(Experimental)
公告解释了 dev 与 build 处理 CJS 依赖的本质差异:
- 构建期:使用
@rollup/plugin-commonjs来支持仅 CJS 的依赖(如 React); - 开发期:用 esbuild 预打包依赖,并在转换用户代码时应用内联 interop 方案。
Vite 3 引入了让 esbuild 在构建期也承担依赖优化的改造,从而可以完全绕过 @rollup/plugin-commonjs,使 dev 与 build 行为一致。由于当时 Rollup v3 即将发布、Vite 还将跟随发布新的大版本,团队决定将其设为可选项(optimizeDeps.enabled 在构建期的开关),“缩小 v3 范围,给 Vite 和生态更多时间磨合新的 CJS interop 方案;框架可以按自己的节奏在 Vite 4 之前切换到构建期 esbuild 依赖优化”。从源码结构看,这一演进最终落地为当前 optimizeDeps 配置在 dev/build 两个环境下的统一处理(docs/config/dep-optimization-options.md)。
5.3 HMR 部分接受(Partial Accept,Experimental)
提供对 HMR Partial Accept 的 opt-in 支持:当一个框架组件模块导出多个绑定(bindings)时,可以只接受其中一部分绑定的更新,解锁更细粒度的 HMR。公告指出该能力对多绑定组件模块尤为关键。当前 Vite 的 HMR 核心(server/hmr 目录与 docs/guide/api-hmr.md 描述的 createHotContext/hot.accept 机制)正是这条演进路线的延续。
六、包体积缩减 30%
Vite 始终把“发布与安装体积”当作特性来对待——“快速安装一个新应用”本身就是体验的一部分。Vite 3 的发布体积比 v2 小 30%:
| 发布体积 (Publish Size) | 安装体积 (Install Size) | |
|---|---|---|
| Vite 2.9.14 | 4.38MB | 19.1MB |
| Vite 3.0.0 | 3.05MB | 17.8MB |
| 缩减 | -30% | -7% |
缩减的关键手段是把“大多数用户用不到”的依赖变为可选:
- Terser 不再默认安装。esbuild 自 Vite 2 起就是 JS 与 CSS 的默认压缩器,Terser 沦为纯可选路径。若使用
build.minify: 'terser',需自行npm add -D terser。当前仓库印证了这一点:packages/vite/package.json 中terser位于peerDependenciesMeta(optional)与 devDependencies 中,而非必装依赖;terser 的加载逻辑独立在 packages/vite/src/node/plugins/terser.ts; - node-forge 移出 monorepo。自动生成 https 证书的功能改为独立插件
@vitejs/plugin-basic-ssl。公告给出的理由很务实:该功能只会生成未加入本地信任库的自签名证书,价值不足以让其常驻核心体积。
七、Bug 清理马拉松
Vite 3 发布前的三个月,由团队新成员主导了一次 issue 清理马拉松:Vite 的 open issues 从 770 个降到 400 个,而同期新增 PR 数量处于历史新高。公告附带的两张趋势图(issues/PRs 存量图与新开图)对应仓库中的 docs/images/v3-open-issues-and-PRs.webp 与 docs/images/v3-new-open-issues-and-PRs.webp。
八、兼容性说明
公告列出的四条兼容性基线(以 v3 为准,迁移路径见 docs/guide/migration.md):
- Node.js 12 / 13 / 15 不再支持(已 EOL),要求 Node.js 14.18+ / 16+;
- Vite 以 ESM 发布,并附带一个指向 ESM 入口的 CJS 代理以兼容 CommonJS 消费者。当前仓库的 packages/vite/package.json 仍是
"type": "module",exports指向./dist/node/index.js,延续这一发布形态; - 现代浏览器基线更新为支持原生 ES Modules、原生 ESM 动态 import 与
import.meta的浏览器; - SSR 与库模式的 JS 文件扩展名改为按格式和包 type 输出合法扩展名(
js/mjs/cjs),而非之前可能出现的无扩展名产物。
九、Vite 核心仓库自身的升级
在打磨 Vite 3 的同时,核心仓库的贡献者体验也得到了系统性升级——这些改进大多在当前仓库中可以直接看到:
- 单元测试与 E2E 测试迁移到 Vitest,更快更稳,同时作为对生态重要基础设施的 dogfooding。当前仓库的测试配置即基于 Vitest:vitest.config.ts 与 vitest.config.e2e.ts;
- VitePress 文档构建纳入 CI;
- 升级到 pnpm 7(当前仓库使用更新的 pnpm workspace:pnpm-workspace.yaml);
- playgrounds 移出 packages 目录至
playground/(公告写为playgrounds,仓库中现已规范为 playground/ 单数目录,内含 assets、hmr、optimize-deps、ssr 等数十个验证场景); - packages 与 playgrounds 全部改为
"type": "module"; - 插件构建改用 unbuild,
plugin-vue-jsx与plugin-legacy迁移到 TypeScript。当前仓库中的 packages/plugin-legacy/ 即为 TypeScript 实现(packages/plugin-legacy/src/ 下 7 个.ts文件)。
十、生态已为 v3 做好准备
官方通过 vite-ecosystem-ci 机制,用 Vite 主分支跑生态头部项目的 CI,在引入回归之前获得及时反馈,确保发布日即兼容大多数基于 Vite 的项目。这一协作模式正是第一节所述“生态维护者反哺核心”的制度化体现。
十一、致谢与后续规划
Vite 3 是 Vite 团队与生态维护者、社区贡献者(公告致谢中列出 600+ 协作者规模下的具体名单,含 HMR Partial Accept 的实现者、VitePress 主题贡献者、西/中/日翻译团队等)集体成果。
“后续规划”部分也勾勒出 v3 之后的路线图:前几个 minor 版本聚焦 issue triage;待 Rollup 大版本发布、插件生态完成更新后,Vite 将跟随发布新的大版本,并借此机会将本次引入的实验特性逐步稳定化。从当前仓库的版本号(8.x)与内容看,这条“年度大版本 + 实验特性渐进转正”的路径被长期执行了下来。
总结:如何阅读这次发布
Vite 3.0 公告的价值在于它完整记录了一次“年度大版本”应包含的全部维度:开发体验(端口、WebSocket、冷启动、glob)、构建与 SSR(ESM 默认、相对 base)、实验特性(路径控制、构建期 esbuild 优化、HMR 部分接受)、体积治理(-30% 发布体积)、兼容性基线(Node/浏览器/ESM 发布)以及核心工程升级(Vitest、pnpm 7、playground 布局)。对照当前仓库源码,这些承诺均可找到落点:端口常量在 constants.ts,glob 在 importMetaGlob.ts,WASM ?init 在 wasm.ts,SSR 外部化在 ssr.md 与 ssr-deps playground 用例中。这份公告因此不仅是一份发布记录,更是一份理解 Vite 版本演进方法论的索引。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
