Vite 6 Environment API:形式化多环境配置,打通 Dev 与 Build 的运行时鸿沟
Environment API 是 Vite 6 引入的核心架构能力:它将原本隐含的 client / ssr 两个环境抽象为一等公民,让框架作者和运行时提供方可以注册任意多个、各自贴近生产运行时约束的环境实例。读完本文,你将理解 Environment API 的设计动机(如何缩小 dev 与 build 之间的行为差异)、environments 配置项的继承规则与选项结构、通过 createEnvironment 提供自定义环境实例的底层机制,以及 Vite 5 用户迁移时需要注意的向后兼容边界。
什么是 Environment API:Vite 6 对“环境”的形式化
根据官方文档 api-environment.md 的说明,Environment API 目前处于 Release Candidate(RC)阶段:Vite 会在主版本之间保持这些 API 的稳定,以便生态实验和基于其构建,但部分具体 API 仍被视为实验性(参见 changes 索引中的 Considering 列表)。Vite 计划在未来某个主版本中(可能伴随破坏性变更)最终稳定这些 API。
在 Vite 5 及之前,只有两个隐式环境:client 和可选的 ssr。Vite 6 将“环境(Environment)”概念形式化后,用户和框架作者可以创建尽可能多的环境,去精确映射应用在生产中的实际运行方式。文档明确指出,这一能力背后是一次大规模的代码内部重构,同时团队投入了大量精力保证向后兼容;Vite 6 的首要目标是让整个生态平滑迁移到新主版本,而非急于让所有用户立即采用新 API。
缩小 Build 与 Dev 之间的鸿沟
对 SPA/MPA 应用:行为完全不变。 对配置层面,Vite 6 没有为这类简单场景暴露任何环境相关的新 API——配置项内部被应用到 client 环境,但配置 Vite 时完全不需要知道这个概念的存在,Vite 5 的配置与行为可以无缝沿用。
对典型的 SSR 应用:两个环境。 典型服务端渲染应用会拥有两个环境:
client:在浏览器中运行应用;ssr:在 Node(或其他服务端运行时)中运行,在页面发送给浏览器之前完成渲染。
Dev 模式下多环境并发运行的架构。 在开发阶段,Vite 过去是在与 dev server 相同的 Node 进程中执行服务端代码,这只是生产环境的一种近似。但服务端代码也可能运行在其他 JS 运行时中(例如 Cloudflare 的 workerd),这些运行时拥有不同的约束条件;现代应用甚至可能同时运行在浏览器、Node 服务器和边缘服务器三种环境里——Vite 5 无法正确表达这些环境。
Vite 6 的核心改进是:在 dev 和 build 两个阶段都可以配置应用的全部环境,并且单个 Vite dev server 现在可以并发运行多套不同环境的代码。具体而言,在共享的 HTTP server、中间件、已解析配置和插件管线之上,dev server 现在持有一组相互独立的 dev 环境实例;每个实例都被配置得尽可能贴近生产环境,并连接到一个 dev 运行时来执行代码(例如 workerd 环境的服务端代码可以在本地通过 miniflare 运行)。浏览器端由浏览器负责 import 并执行代码,其他环境则由 module runner 拉取并求值转换后的代码:
从源码结构看,这一“非 client 环境连接 dev 运行时”的设计有明确落点:packages/vite/src/node/config.ts#L272-L274 中的 defaultCreateDevEnvironment 对所有非 client 环境调用 createRunnableDevEnvironment(即可运行的、通过 ModuleRunner 执行代码的环境),而 packages/vite/src/node/config.ts#L260-L270 中的 defaultCreateClientDevEnvironment 则创建带 HMR 通道、直接由浏览器 import 代码的标准 client 环境。
环境配置:environments 选项与继承规则
SPA/MPA 配置保持 Vite 5 形态
对 SPA/MPA 应用,配置与 Vite 5 类似——这些选项在内部用于配置 client 环境:
export default defineConfig({
build: {
sourcemap: false,
},
optimizeDeps: {
include: ['lib'],
},
})
文档强调这一设计的意义:保持 Vite 的低门槛(approachable),在确实需要之前不暴露新概念。
多环境应用通过 environments 显式声明
当应用由多个环境组成时,用 environments 配置项显式配置:
export default {
build: {
sourcemap: false,
},
optimizeDeps: {
include: ['lib'],
},
environments: {
server: {},
edge: {
resolve: {
noExternal: true,
},
},
},
}
选项继承规则
未在文档中特别说明的情况下,环境会继承顶层配置选项。上例中新建的 server 和 edge 环境都会继承 build.sourcemap: false。但有少数顶层选项只作用于 client 环境——例如 optimizeDeps,因为它作为服务端环境的默认值并不合理,这些选项在 配置参考 中带有 NonInherit 徽章。client 环境本身也可以通过 environments.client 显式配置,但官方推荐继续用顶层选项配置 client,这样在新增环境时 client 配置可以保持不变。
EnvironmentOptions 的完整结构
文档中给出的接口概览是:
interface EnvironmentOptions {
define?: Record<string, any>
resolve?: EnvironmentResolveOptions
optimizeDeps: DepOptimizationOptions
consumer?: 'client' | 'server'
dev: DevOptions
build: BuildOptions
}
结合源码可以看到更完整的划分。EnvironmentOptions 在 packages/vite/src/node/config.ts#L335-L344 中定义为 SharedEnvironmentOptions 加上 dev / build 两个分支。其中共用的 SharedEnvironmentOptions 还包括:
input:该环境的应用入口(相对项目根目录解析);consumer:标记环境消费方,'client'或'server',非 client 环境默认按'server'处理;keepProcessEnv:为true时代码中的process.env保留原样、在运行时求值,否则被静态替换为空对象;isBundled(实验性):显式声明该环境是否产出 bundle 化输出——build 时所有环境默认为true,serve 时仅当启用experimental.bundledDev时 client 环境为true,其余为false。
dev 专属选项 DevEnvironmentOptions 包括:
warmup:待预转换的文件列表,支持 glob;preTransformRequests:是否预转换已知直接依赖,client 环境默认true,其余环境默认false;sourcemap/sourcemapIgnoreList:dev 阶段 sourcemap 控制,以及生成x_google_ignoreList忽略列表的规则(默认排除node_modules路径);createEnvironment:低层钩子,自定义 Dev Environment 实例的创建(后文详述);recoverable(实验性):对支持 full-reload 的环境(如 client),在重启服务器时可提前中断当前文件处理;moduleRunnerTransform:标记该环境关联 module runner——client 默认false,非 client 环境默认true。
build 专属选项 BuildEnvironmentOptions 定义在 packages/vite/src/node/build.ts#L92(如 outDir 等)。另外,optimizeDeps 虽只作用于 dev,但出于向后兼容保留了顶层位置,而非嵌套在 dev 下。
UserConfig 与环境生命周期
UserConfig 继承自 EnvironmentOptions,使顶层配置同时充当 client 配置和其他环境的默认值(通过 environments 选项覆盖):
interface UserConfig extends EnvironmentOptions {
environments: Record<string, EnvironmentOptions>
// other options
}
这一点在源码中得到印证:packages/vite/src/node/config.ts#L370 处 UserConfig extends DefaultEnvironmentOptions,而配置解析阶段通过 packages/vite/src/node/config.ts#L1722-L1726 的循环对 config.environments 中的每个环境逐一调用 resolveEnvironmentOptions,产出 resolvedEnvironments 记录。
各阶段环境的存在规则:
- dev 阶段:
client和一个名为ssr的服务端环境始终存在,用于兼容server.ssrLoadModule(url)与server.moduleGraph; - build 阶段:
client环境始终存在;ssr环境仅在显式配置时存在(通过environments.ssr,或出于向后兼容通过build.ssr)。应用并不必须叫ssr,可以命名为server等任意名字。
注意:顶层 ssr 属性将在 Environment API 稳定后被弃用。它的作用与 environments 相同,但仅面向默认的 ssr 环境,且只允许配置一小部分选项。
自定义环境实例:供运行时提供方接入
对于运行时提供方(runtime providers),Vite 暴露了低层配置 API,使其能提供带有正确运行时默认值的环境。这些环境甚至可以在 dev 阶段派生其他进程或线程来运行模块,从而得到一个更接近生产环境的运行时。文档给出的例子是 Cloudflare Vite 插件:它使用 Environment API 在开发期间将代码运行在 Cloudflare Workers 运行时(workerd)中,通过运行时时提供方的 customEnvironment 助手完成注册:
import { customEnvironment } from 'vite-environment-provider'
export default {
build: {
outDir: '/dist/client',
},
environments: {
ssr: customEnvironment({
build: {
outDir: '/dist/ssr',
},
}),
},
}
在 Vite 内核侧,这一能力的落点是 dev.createEnvironment 选项:packages/vite/src/node/config.ts#L235-L242 中它接收 (name, config, context),可返回任意 Promise<DevEnvironment> | DevEnvironment。从源码结构看,Vite 内置了 defaultCreateClientDevEnvironment 与 defaultCreateDevEnvironment 两条默认路径,运行时提供方则通过该钩子完全替换实例创建逻辑(customEnvironment 本身来自运行时时提供方的独立包,不在 Vite 仓库源码内)。
向后兼容性
官方文档明确列出了当前的兼容边界:
- 当前 Vite server API 尚未弃用,与 Vite 5 向后兼容;
server.moduleGraph返回 client 与 ssr 模块图的混合视图,其所有方法都会返回向后兼容的混合模块节点;传入handleHotUpdate的模块节点采用相同方案。
文档同时建议暂不迁移到 Environment API:目标是先让足够多的用户采用 Vite 6,避免插件需要维护两个版本的 API。关于未来弃用与升级路径,仓库中对应的 change 文档包括:
this.environmentin Hooks- HMR
hotUpdatePlugin Hook - Move to Per-environment APIs
- SSR Using
ModuleRunnerAPI
目标读者与配套指南
api-environment.md 面向最终用户讲解环境的基本概念;仓库中还按角色拆分为三份进阶指南:
- 插件作者:Environment API for Plugins 介绍了统一的按环境 API——
this.environment上下文、configEnvironment/hotUpdate/applyToEnvironment钩子,以及构建阶段的共享插件管线(sharedDuringBuild); - 框架作者:Environment API for Frameworks 讲解以编程方式暴露环境的框架侧用法;
- 运行时提供方:Environment API for Runtimes 说明如何向框架和用户交付自定义环境。
小结与适用前提
Environment API 的本质,是把 Vite dev server 从“一个面向浏览器 + 一个近似 Node 的 SSR 环境”重构为“共享管线之上 N 个独立、可贴近生产的 dev 环境”。当前使用它的前提是接受 RC 阶段的定位:API 在主版本间保持稳定但个别部分仍实验性,顶层 ssr 选项未来会弃用,build 阶段各环境共享插件管线需通过 builder.sharedConfigBuild / sharedDuringBuild 显式开启。普通 SPA/MPA 项目可以完全无感;而构建多运行时应用(浏览器 + Node + 边缘)的团队,则应结合 api-environment.md 与三份角色指南,规划从 Vite 5 到 Environment API 的迁移路径。
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 StartedRust0624
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