Vite create-vite 版本演进深度解析:从 @vitejs/create-app 到多包管理器、React Compiler 支持的脚手架
【免费下载链接】viteNext generation frontend tooling. It's fast!项目地址: https://gitcode.com/GitHub_Trending/vi/vite
本文以 create-vite 的 CHANGELOG 为主线,梳理这个 Vite 官方项目脚手架工具从 2021 年 1 月首个版本到当前 9.2.0 的完整演进脉络,并结合 核心源码 与 模板目录结构 剖析其命令行参数、模板体系与包管理器适配的底层实现,帮助你在升级或排查脚手架行为时快速定位对应版本引入的能力与破坏性变更。
一、create-vite 在 Vite 仓库中的定位
create-vite是 Vite monorepo 中负责"脚手架"的独立包,位于 packages/create-vite。从 package.json 可以确认它的几个关键身份特征:
- npm 包名与版本:
create-vite,当前版本9.2.0,即 CHANGELOG 最顶部记录的版本; - 可执行入口:
bin字段同时注册了create-vite和缩写命令cva,二者都指向 index.js,后者仅做一行转发——import './dist/index.js',真正逻辑位于 tsdown 构建产物中; - Node 版本要求:
engines声明"node": "^20.19.0 || >=22.12.0",这一约束正是 7.0.0 版本破坏性变更(见后文)的直接产物; - 发布内容:
files字段为index.js、template-*和dist,说明模板目录是随 npm 包一起分发的; - 运行时依赖:
@clack/prompts(交互式提示)、@vercel/detect-agent(AI Agent 环境检测)、cross-spawn(跨平台子进程)、mri(命令行参数解析)。
源码只有一个入口文件 src/index.ts,所有 CLI 逻辑、框架/变体注册表、模板复制与后处理逻辑都集中在这一处,这使得 CHANGELOG 中每一条与脚手架行为相关的改动基本都能在该文件中找到对应实现。
二、版本时间线:CHANGELOG 中的关键里程碑
CHANGELOG.md 覆盖了从1.0.0(2021-01-02)到9.2.0(2026-08-24)的全部发布记录。按时间线提取对使用者最有价值的事件,可以得到下面这张里程碑表:
| 版本 | 时间 | 关键变化 | 类别 |
|---|---|---|---|
| 1.0.0 | 2021-01 | 包诞生,最初名为@vitejs/create-app,提供首批模板 | 首发 |
| 2.5.0 | 2021-07 | 正式更名为create-vite,命令简化为npm init vite@latest | 改名 |
| 3.0.0 | 2022-07 | 移除 Node 12 支持;最低 Node 14.18;模板迁移 ESM;支持嵌套目录 | 破坏性变更 |
| 3.1.0 | 2022-09 | 支持自定义 init 命令(create-vue、Nuxt、SvelteKit);源码迁移 TypeScript | 功能 |
| 4.2.0 | 2023-03 | 支持create-electron-vite透传 | 功能 |
| 4.4.0 | 2023-07 | 新增 Solid、Qwik 模板;Bun 作为脚本运行器的适配 | 功能 |
| 5.0.0 | 2023-11 | 模板全面升级到 Vite 5;最低 Node 18 | 破坏性变更 |
| 6.4.0 | 2025-04 | 新增 TanStack Router 命令 | 功能 |
| 6.5.0 | 2025-05 | 新增 Marko、RedwoodSDK 入口 | 功能 |
| 7.0.0 | 2025-06 | 要求 Node 20.19+/22.12+,移除 CJS 构建,移除 Node 18;build.target提升并命名baseline-widely-available | 破坏性变更 |
| 8.0.0-beta.0 | 2025-09 | --interactive/--no-interactive开关;自动安装依赖并启动 dev;React Compiler 支持 | 功能 |
| 8.2.0 | 2025-11 | 新增 Vike 入口 | 功能 |
| 9.0.0 | 2026-03 | 默认浏览器 target 更新;AI Agent 体验(AX)支持;新增 Ember 入口;移除 react-swc 变体;模板变体显示说明文字 | 破坏性变更 + 功能 |
| 9.1.0 | 2026-06 | React 模板默认改用Oxlint,并提供 ESLint 选项;tsconfig.node.json采用moduleResolution: nodenext | 功能 |
| 9.2.0 | 2026-08 | 新增nub 包管理器支持;修复对非 React 模板传--eslint时崩溃的问题 | 功能 + 修复 |
几个值得注意的细节:
- 版本号语义。Changelog 中每次大版本都会在开头给出
⚠ BREAKING CHANGES小节(如 7.0.0 的 "bump required node version to 20.19+, 22.12+ and remove cjs build"),并在正文对应条目重复出现;而 patch 版本(如 9.1.2、9.0.7)的标题被<small>标签包裹,用来在视觉上弱化非功能类修复。 - 高频的依赖升级条目。大量
update all non-major dependencies/update rolldown-related dependencies条目来自 Renovate 的自动依赖更新(源码中的// renovate: datasource=npm注释即为证据),这类条目对使用者无行为影响,阅读时可跳过。 - 模板文件的许可证。6.x 期间有一条 "mark template files as CC0" 的改动,说明
template-*目录下的示例代码采用 CC0 许可,与工具本身的 MIT 许可区分开,方便你直接取用模板代码而不受 MIT 义务约束(具体以仓库内 LICENSE 为准)。
三、CLI 使用方式:命令、参数与模板清单
3.1 启动命令
按 README 的当前说明,各包管理器的启动方式如下(Node 需满足 20.19+ / 22.12+,个别模板可能需要更高版本):
# npm npm create vite@latest # yarn yarn create vite # pnpm pnpm create vite # bun bun create vite # deno deno init --npm vite跳过交互、直接指定项目名与模板时,npm 7+ 需要额外的双连字符(这正是 CHANGELOG 9.0.0 中 "handle double dash fornpm exec" 修复所处理的场景):
# npm 7+,注意 -- 之后才是传给 create-vite 的参数 npm create vite@latest my-vue-app -- --template vue # 其他包管理器 yarn create vite my-vue-app --template vue pnpm create vite my-vue-app --template vue bun create vite my-vue-app --template vue deno init --npm vite my-vue-app --template vue项目名可以使用.表示在当前目录脚手架。
3.2 完整选项列表
以下选项表来自 src/index.ts 中的helpMessage(执行-h或--help时打印,9.1.0 曾专门扩充过帮助输出中的 flag 数量):
Usage: create-vite [OPTION]... [DIRECTORY] Create a new Vite project in JavaScript or TypeScript. When running in TTY, the CLI will start in interactive mode. Options: -t, --template NAME use a specific template -i, --immediate / --no-immediate install dependencies and start dev --eslint / --no-eslint use ESLint instead of Oxlint (only for React templates) --overwrite remove existing files if target directory is not empty --interactive / --no-interactive force interactive / non-interactive mode -h, --help display this help message参数解析在 src/index.ts#L25-L36 中通过mri完成,help、overwrite、immediate、interactive、eslint全部声明为 boolean,因此--no-xxx形式天然可用。各参数的演进来源可在 CHANGELOG 中追溯:
--template:最早期的核心参数;--overwrite:5.2.0 引入("allow overwrite in command line"),用于非交互场景下处理非空目录;--interactive/--no-interactive:8.0.0-beta.0 引入;6.4.1 曾临时修复过强制交互的 flag 问题;--immediate:8.0.0-beta.0 的 "support auto install dependencies and start dev" 引入,8.0.0 又调整了提问顺序(先问是否使用 rolldown-vite,再问是否自动安装);--eslint:9.1.0 引入,9.1.2 修复了它对非 React 模板会崩溃的 bug(现在只打印一条 "will be ignored" 警告)。
3.3 模板清单
内置模板与 README 中列出的 18 个 preset 一致,与helpMessage的"Available templates"部分一一对应:
vanilla vanilla-ts vue vue-ts react react-ts react-compiler react-compiler-ts preact preact-ts lit lit-ts svelte svelte-ts solid solid-ts qwik qwik-ts这些名称不是手写的清单,而是从源码中的FRAMEWORKS注册表推导出来的:src/index.ts#L80-L392 定义了每个框架及其变体,TEMPLATES常量再把它展平为全部模板名的数组。9.0.0 起,交互式选择变体时还会显示说明文字("show description for template variants"),例如react-compiler变体显示为 "JavaScript + React Compiler"。
除内置模板外,注册表里还有两类自定义命令入口(customCommand字段):
- 指向其他官方/生态工具的透传脚手架,如
custom-create-vue(npm create vue@latest)、custom-nuxt(nuxi init)、SvelteKit、React Router v7、TanStack Router、QwikCity、Ember、Angular/Analog、Marko Run、Vike、RedwoodSDK 等; - "Others" 分组下的社区聚合入口:
create-vite-extra与create-electron-vite。
这类条目正是 CHANGELOG 中长期迭代的主题(3.1.0 引入机制,4.2.0 加 Electron,6.4.0 加 TanStack Router,6.5.0 加 Marko/Redwood,8.2.0 加 Vike,9.0.0 加 Ember)。对于不在内置模板中的社区项目,README 建议使用 tiged 手动脚手架:
npx tiged user/project my-project cd my-project npm install npm run dev四、源码级实现:一次脚手架运行的完整流程
4.1 init() 主干流程
入口函数init()(src/index.ts#L440-L733)按注释划分为若干阶段,与 CHANGELOG 各版本功能一一对应:
- 参数与环境判定。解析
argv._[0]为目标目录;interactive默认为process.stdin.isTTY(--interactive/--no-interactive可覆盖)。随后调用@vercel/detect-agent的determineAgent()检测是否运行在 AI Agent 环境中——这就是 9.0.0 的 "add AI agent experience (AX) support":若识别到 Agent 且处于交互模式,会额外打印一条提示,建议改用create-vite <DIRECTORY> --no-interactive --template <TEMPLATE>一步完成。 - 项目名与目标目录。交互模式询问 "Project name:"(默认
vite-project),非交互模式直接取默认值;输入会经过formatTargetDir(L735-L740)剥离非法字符<>:"\|?*与结尾斜杠——对应 CHANGELOG 中 "strip invalid characters in project name"(9.0.0)等修复。 - 非空目录处理。若目标目录已存在且非空(目录仅含
.git视为空),交互模式下提供 Cancel / Remove / Ignore 三个选项;--overwrite等价于选择 Remove,非交互且未传 flag 时直接取消。emptyDir(L780-L790)会清空目录但保留.git,对应 CHANGELOG 中 3.1.0 的 "skip.gitwhen emptying dir"。 - 包名推导与校验。取目录名的 basename,用正则
isValidPackageName校验,不合法时用toValidPackageName自动修正(小写化、空格转连字符),交互模式下还会再询问确认——这是 2.1.0 起的 "ensure valid package name" 系列修复的延续。 - 框架与变体选择。
--template给的值若不在TEMPLATES中,交互模式下会提示"xxx" isn't a valid template并重新选择;非交互模式静默回退到vanilla-ts。 - React Compiler 模板归一化。若模板名包含
react-compiler(L606-L611),会剥掉-compiler后缀,实际复制template-react/template-react-ts目录,然后由setupReactCompiler()做后处理(见 4.4 节)。 - customCommand 透传。若所选变体带
customCommand,则直接spawn.sync执行改写后的外部命令并process.exit——这是 Nuxt、SvelteKit、Ember 等"借道"入口的实现;9.0.0 还修复了这类命令不应预创建空目录的问题("do not create empty directory for custom commands")。 - Lint 选择。React 模板在交互模式会询问 "Which linter to use?"(9.1.1 把措辞改为现在这样),默认 Oxlint,可选 ESLint;
--eslint只对 React 模板生效,其他模板传了只收到警告(9.1.2 修复)。 - 是否立即安装启动。交互模式询问 "Install with and start now?",非交互默认否;选是则依次执行安装与
dev脚本。 - 文件写入与后处理。递归复制
template-<name>目录(跳过模板自身 package.json,稍后重写),其中index.html的<title>会被替换为项目名(8.0.0-beta.0 的 "set default title in index.html to project name"),_gitignore、_oxlintrc.json通过renameFiles映射表(L394-L397)改回点开头文件名(npm 不支持发布点文件)。最后package.json的name字段被改写为第 3 步得到的包名。
4.2 包管理器识别与命令改写
install()/start()(L414-L438)通过pkgFromUserAgent(process.env.npm_config_user_agent)识别调用方:解析npm_config_user_agent的首个 token(形如pnpm/9.1.0),取斜杠前半为包管理器名。识别结果决定后续所有命令形态:
- 安装命令:yarn 直接
yarn,其余为<pm> install; - 运行脚本:
yarn/pnpm/bun dev、deno task dev、其余<pm> run dev(L1111-L1139)——CHANGELOG 8.0.0 中 "use shorter command name forrun devfor each package manager" 说的就是这里。
外部customCommand的改写逻辑集中在getFullCustomCommand()(L1053-L1109),它按包管理器把npm create .../npm exec ...逐一替换:
| 包管理器 | npm create xxx改写为 | npm exec xxx改写为 |
|---|---|---|
| bun | bun x create-xxx | bun x xxx |
| nub | nubx create-xxx | nubx xxx |
| deno | deno run -A npm:create-xxx | deno run -A npm:xxx |
| pnpm | pnpm create xxx(不支持--语法) | pnpm dlx xxx |
| yarn 1.x | 去掉@latest(旧版不支持) | 保持npm exec |
| 其他 | <pm> create xxx | <pm> dlx或npm exec |
其中nub 的支持正是 CHANGELOG 最新版本 9.2.0 的 "add nub package manager support",Bun 与 Deno 的适配分别可追溯到 4.4.0 和 7.1.3。测试环境下,install()/start()会检测_VITE_TEST_CLI环境变量并跳过真实执行,这为tests下的自动化测试提供了桩(stub)机制。
4.3 交互式 UI 的演进
Changelog 能清晰看到提示库的三次迁移:2.x 时代使用 prompts(5.3.0 移除了 prompts alias),6.3.0 换用@clack/prompts("use@clack/prompts",5.5.4 又曾回退 svelte 相关依赖以配合),9.0.5 用 Node 内置util.styleText替换了颜色库("use styleText"),对应源码中createColors()的 Proxy 包装(L1143-L1150)。框架选择时每个变体的hint字段还会展示改写后的完整外部命令,帮助用户在不选透传入口的情况下也能手动运行官方脚手架。
4.4 React Compiler 与 ESLint 的后处理
React Compiler(8.0.0-beta.0 首次引入,8.1.0 将依赖升到 1.0.0,9.0.1 补上缺失的@babel/core依赖)的实现是setupReactCompiler()(L807-L857):
- 向
package.json的devDependencies注入@rolldown/plugin-babel、babel-plugin-react-compiler、@babel/core,TS 模板额外注入@types/babel__core(版本号带// renovate注释,由 Renovate 自动维护); - 改写
vite.config.*,把import react from '@vitejs/plugin-react'扩展为同时引入reactCompilerPreset与babel插件,并在plugins数组中追加babel({ presets: [reactCompilerPreset()] }); - 更新模板 README 的 "React Compiler" 章节,提示该方案会影响 dev/build 性能,并指向 plugin-react 的 experimental 原生编译器支持(9.2.0 的 "mention experimental react compiler support" 即此改动的措辞更新)。
ESLint 选项(9.1.0 引入)的setupEslint()(L859-L1030)则做相反方向的替换:删除模板默认的.oxlintrc.json,按 TS/JS 两套配置生成eslint.config.js(flat config,defineConfig+globalIgnores,TS 版包含typescript-eslintrecommended),向 devDependencies 写入eslint、@eslint/js、eslint-plugin-react-hooks、eslint-plugin-react-refresh、globals等版本固定依赖,把scripts.lint改为eslint .,并同步改写 README 中 "Expanding the ESLint configuration" 小节(含 type-aware 与 react-x/react-dom 的进阶配置示例)。9.0.6 的 "use ESLint v10" 说明这里的版本基线已对齐 ESLint 10 的 flat-config-only 形态。
五、模板目录与构建体系
template-*目录是 npm 发布的核心资产之一。以 template-react-ts 为例,它包含完整的tsconfig体系(tsconfig.json为 solution 风格根配置——5.3.0 引入,让vite.config.ts参与类型检查)、vite.config.ts、src/、index.html与 README。CHANGELOG 中与模板内容相关的修复都能在这些目录中找到痕迹,例如:
- 9.0.2:给 vue 模板组件补上
lang="ts"修复 vue-ts 类型错误; - 9.1.0 / 9.1.1:
tsconfig.node.json引入moduleResolution: nodenext(先误加moduleResolution又被 9.1.0 的后续条目修正); - 6.1.0:vue-ts 模板改为继承
@vue/tsconfig简化配置; - 9.0.0:React 模板适配新版
@vitejs/plugin-react,Svelte 模板不再默认vitePreprocess,react-swc 变体被整体移除。
构建侧,该包使用 tsdown.config.ts 定义的 tsdown 流水线(7.0.0 从 unbuild 迁移到 tsdown),package.json的dev/build/typecheck脚本与 9.0.4 中 "handle tsdown inlineOnly deprecation" 的构建系统条目相对应。类型检查由独立的 tsconfig.json 驱动。
六、阅读与升级建议
- 查当前版本:以 package.json 的
version字段为准(当前 9.2.0),而非只依赖 CHANGELOG 顶部条目; - 跨大版本迁移:7.0.0 起需要 Node 20.19+/22.12+ 且不再有 CJS 构建;8.x 引入了
--interactive、自动安装与 React Compiler 模板;9.0.0 提升了默认浏览器 target 并调整了模板集(移除 react-swc、新增 Ember 与 AX 提示); - 非交互/CI 场景:优先使用
--no-interactive --template <name>全参数形式(Agent 环境的提示语也是这一形态);处理已有目录时显式传--overwrite; - 透传入口排障:当 create-vite 实际执行的是
customCommand(如npm create vue@latest)时,其行为由外部工具决定,create-vite 只负责按 4.2 节的规则改写命令前缀,相关 issue 应到对应项目排查。
七、小结
packages/create-vite/CHANGELOG.md记录了 create-vite 五年间从@vitejs/create-app更名、TypeScript 化、clack 交互重构,到 rolldown 时代的多包管理器适配(npm/yarn/pnpm/bun/deno/nub)、React Compiler 一键注入与 Oxlint/ESLint 双轨 lint 体系的完整过程。结合 src/index.ts 中清晰的阶段化init()流程、FRAMEWORKS注册表与getFullCustomCommand()的命令改写矩阵,可以确认:这份 CHANGELOG 中的每一条面向使用者的改动,其实现与行为边界都能在单文件源码中找到落点,这也是把它作为升级决策与行为排障依据的价值所在。
【免费下载链接】viteNext generation frontend tooling. It's fast!项目地址: https://gitcode.com/GitHub_Trending/vi/vite
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考