首页
/ 深入 create-vite:Vite 官方脚手架 CLI 从一条命令到可运行项目的完整解析

深入 create-vite:Vite 官方脚手架 CLI 从一条命令到可运行项目的完整解析

2026-09-04 12:51:21作者:鲍丁臣Ursa

create-vite 是 Vite 官方提供的项目脚手架工具(位于 packages/create-vite),一条 npm create vite@latest 即可在当前目录生成一个选定框架的完整工程。本文基于仓库内 README 与主源码 src/index.ts,完整梳理它的调用方式、全部 CLI 参数、18 个内置模板、交互式流程的每一步判定逻辑,以及模板复制、文件名重命名、React Compiler / ESLint 后置改造等底层实现,帮助读者既能正确上手,也能理解“脚手架到底替你做了什么”。

一、环境要求与安装调用方式

README 明确标注了兼容性前提:

Vite 要求 Node.js 20.19+ 或 22.12+;部分模板可能要求更高的 Node.js 版本,若包管理器给出告警请升级。

这一约束在 package.jsonengines 字段中得到印证:"node": "^20.19.0 || >=22.12.0",当前仓库中的版本为 9.2.0

不同包管理器的入口命令如下(与 README 完全一致):

# NPM
npm create vite@latest

# Yarn
yarn create vite

# PNPM
pnpm create vite

# Bun
bun create vite

# Deno
deno init --npm vite

不带参数运行时,CLI 在 TTY 下会进入交互式模式(源码中通过 process.stdin.isTTY 判断,见 src/index.ts#L456),依次询问项目名称、框架、变体、Linter 与是否立即安装启动。

直接指定项目名与模板

也可以跳过交互,用命令行参数直接指定项目名和模板。以生成 Vite + Vue 项目为例(注意 README 特别指出 npm 7+ 需要多一个双横线 -- 才能把参数透传给脚手架):

# npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-app -- --template vue

# yarn
yarn create vite my-vue-app --template vue

# pnpm
pnpm create vite my-vue-app --template vue

# Bun
bun create vite my-vue-app --template vue

# Deno
deno init --npm vite my-vue-app --template vue

另外,项目名可以用 . 表示“在当前目录搭建”,这在已有仓库目录里做二次初始化时很常用。

二、CLI 参数全集

--help(或 -h)输出的帮助信息定义在 src/index.ts#L40-L63,参数解析使用 mri 完成(src/index.ts#L25-L36)。整理如下:

参数 别名 类型 说明
DIRECTORY 位置参数 目标目录;. 表示当前目录
-t, --template NAME -t 字符串 直接使用指定模板,跳过框架选择
-i, --immediate / --no-immediate -i 布尔 搭建完成后立即安装依赖并启动 dev server
--eslint / --no-eslint 布尔 React 模板改用 ESLint 而非默认的 Oxlint
--overwrite 布尔 目标目录非空时移除已有文件后继续
--interactive / --no-interactive 布尔 强制交互 / 非交互模式
-h, --help -h 布尔 打印帮助信息

几个从源码可以确认的行为细节:

  • 模板名会被规范化:react-compiler / react-compiler-ts 在解析时会剥掉 -compiler 后缀,实际落盘模板对应 react / react-ts,只是额外做一层编译器改造(src/index.ts#L606-L611)。
  • 传入无效模板名时,交互模式会提示 "xxx" isn't a valid template. Please choose from below: 并回到框架选择菜单;非交互模式则直接落到默认模板(src/index.ts#L557-L601)。
  • 非交互模式(无 TTY 且未传 --interactive)下的默认值是:目标目录 vite-project、模板 vanilla-ts、不立即安装启动src/index.ts#L486L599L664-L666)。这意味着 create-vite 天然适合被脚本或 Agent 以 --no-interactive --template xxx 的方式一次性调用。

三、内置模板与交互式两级选择

README 列出的内置模板预设共 18 个:

vanillavanilla-tsvuevue-tsreactreact-compilerreact-tsreact-compiler-tspreactpreact-tslitlit-tssveltesvelte-tssolidsolid-tsqwikqwik-ts

这些模板以 template-<name> 目录的形式随包发布——package.jsonfiles 字段显式包含了 template-*dist。仓库中可以逐一查看每个模板的完整内容,例如 template-reacttemplate-vuetemplate-svelte-ts

交互式模式下,选择分两级,对应 FRAMEWORKS 数据结构:

  1. Select a framework:Vanilla、Vue、React、Preact、Lit、Svelte、Solid、Ember、Qwik、Angular、Marko、Others;
  2. Select a variant:TypeScript / JavaScript,以及各框架的“外部脚手架变体”(如 Vue 下的 Official Vue StarterNuxtVike,React 下的 RSCReact Router v7TanStack RouterRedwoodSDK 等)。

值得注意:Ember、Angular、Marko 以及 Others 组下的所有选项都没有对应的 template-* 目录,它们携带的是 customCommand 字段(src/index.ts#L293-L386)。选中后 CLI 不会复制本地模板,而是直接把 TARGET_DIR 占位符替换成你的目标目录,用 spawn.sync 调起外部命令,例如 Nuxt 的 npm exec nuxi init TARGET_DIR、SvelteKit 的 npm exec sv create TARGET_DIR、Angular 的 npm exec @angular/cli@latest new TARGET_DIRsrc/index.ts#L613-L628)。

包管理器自适应

外部命令在生成前会经过 getFullCustomCommand 改写,以适配当前使用的包管理器:npm create 在 bun 下变成 bun x create-、在 deno 下变成 deno run -A npm:create-npm exec 在 pnpm 下变成 pnpm dlx、在 yarn 下变成 yarn dlx。这个判断依据来自 npm_config_user_agent 环境变量(pkgFromUserAgent),解析不出时回退为 npm

四、脚手架落盘:复制、重命名与内容替换

当所选模板是内置模板时,核心流程在 init 的第 5~6 步之后完成,具体做了四件事:

1. 确定模板源目录。 以 CLI 自身所在包目录为基准解析 template-<template>src/index.ts#L673-L677)。

2. 逐文件复制,并做点文件重命名。 模板目录中所有非 package.json 文件通过递归 copy 写入目标目录,其中下划线前缀文件会被改写为点前缀:

const renameFiles: Record<string, string | undefined> = {
  _gitignore: '.gitignore',
  '_oxlintrc.json': '.oxlintrc.json',
}

src/index.ts#L394-L397)之所以在模板里用 _gitignore 而不是 .gitignore,是因为部分包管理器和发布流程对点文件支持不佳。这一点在测试文件 cli.spec.ts#L35-L39 中也有同名映射来校验生成的文件清单与模板目录完全一致。

3. 替换 index.html 标题与 package.json 名称。 write 函数对 index.html 做特殊处理——用正则替换 <title> 为包名(src/index.ts#L679-L694),测试用例 “sets index.html title to project name”(cli.spec.ts#L299-L309)验证了 <title>test-app</title> 的生成结果。package.json 则不直接复制,而是读取模板版本、仅改写 name 字段后重新序列化写出(src/index.ts#L701-L707)。

4. 目录名 → 包名的合法性处理。 包名默认取目标目录的 basename,经 isValidPackageName 正则校验;不合法时交互模式下会追问,非交互模式则自动执行 toValidPackageName 的转换:去空格转连字符、小写化、去掉开头的 ./_。同样,目录名本身也会经过 formatTargetDir 清洗,剥离 <>:"\|?* 等非法字符和结尾斜杠。

目标目录非空时的三种处置

若目标目录已存在且非空(isEmpty 认为只有 .git 也算空目录),CLI 提供三个选项(src/index.ts#L490-L533):

  • Cancel operation:取消;
  • Remove existing files and continue:执行 emptyDir 清空目录——注意它会保留 .git,方便在已有 git 仓库内重新初始化;
  • Ignore files and continue:不清空,直接覆盖同名文件。

非交互模式下若未显式传 --overwrite,默认按“取消”处理;传了 --overwrite 则等价于选“移除已有文件”。测试用例 “asks to overwrite non-empty target directory”(cli.spec.ts#L108-L130)覆盖了普通子目录、嵌套子目录和当前目录三种场景。

五、React 模板的后置改造:React Compiler 与 Linter 选择

这是 create-vite 中最复杂的部分,两个变体都有独立开关与实现函数。

React Compiler(react-compiler / react-compiler-ts 模板)

选中后,setupReactCompiler 会对落盘项目做三处修改:

  1. devDependencies 注入 @rolldown/plugin-babelbabel-plugin-react-compiler@babel/core(TS 版再加 @types/babel__core);
  2. 改写 vite.config.ts/js:引入 reactCompilerPresetbabel 插件,把 plugins: [react()] 替换为:
plugins: [
  react(),
  babel({ presets: [reactCompilerPreset()] })
],
  1. 更新生成项目的 README,说明已启用 React Compiler 并提示其会“impact Vite dev & build performances”,同时提到可在 plugin-react 选项中尝试实验性的原生 compiler: true 支持。

对应测试 “successfully scaffolds a project based on react-compiler-ts starter template”(cli.spec.ts#L175-L194)断言了配置文件中出现 reactCompilerPresetpackage.json 出现 babel-plugin-react-compiler、README 出现启用提示。

Linter:默认 Oxlint,可选 ESLint(仅 React 模板)

当前版本的 React 模板默认使用 Oxlint:模板目录自带 _oxlintrc.json,脚手架将其重命名为 .oxlintrc.jsonlint 脚本为 oxlint。测试 “scaffolds react-ts with Oxlint by default”(cli.spec.ts#L196-L213)验证了默认产物中 .oxlintrc.json 存在、eslint.config.js 不存在、依赖中无 eslint。

--eslint 则进入 setupEslint:删除 .oxlintrc.json,写入 flat-config 风格的 eslint.config.js(TS 版含 typescript-eslint recommended,JS 版含 jsx parserOptions 与 eslint-plugin-react-refresh),把 lint 脚本改写为 eslint .,并同步替换依赖与生成项目 README 中“Expanding the Oxlint configuration”章节为对应的 ESLint 章节。若对非 React 模板误传 --eslint,CLI 会打印警告 “--eslint is only supported for React templates and will be ignored” 并忽略该参数(src/index.ts#L630-L638),行为由 cli.spec.ts#L230-L245 保证。

六、--immediate:自动安装并启动

脚手架结束后是否立即安装依赖并启动 dev server,交互模式下会询问 “Install with <pkgManager> and start now?”;--immediate / --no-immediate 可跳过询问(默认 false)。选择立即执行时:

  • install 按包管理器生成安装命令——yarn 是裸 yarn,其余是 <pm> install,以 stdio: 'inherit' 在目标目录同步执行;
  • start 调用 getRunCommand:yarn / pnpm / bun 直接 <pm> dev,deno 为 deno task dev,其余(npm)为 npm run dev

非交互且未选 immediate 时,CLI 输出收尾提示,按当前包管理器拼好后续三步命令(cd、安装、dev),例如:

Done. Now run:

  cd my-vue-app
  npm install
  npm run dev

测试 “accepts immediate flag” 与 “accepts immediate flag and skips install prompt”(cli.spec.ts#L311-L327)分别验证了两种路径。

七、面向 Agent 的友好性与测试策略

有两点设计值得工程视角关注:

AI Agent 检测。 CLI 通过 @vercel/detect-agent 探测运行环境是否为 Agent(src/index.ts#L458-L464)。若是,且在交互式 TTY 中,会主动打印一行提示,推荐改用一次性命令:

create-vite <DIRECTORY> --no-interactive --template <TEMPLATE>

这与第二节所述的非交互默认值设计配合,使脚本化调用结果确定、可预测。

测试如何跑真实 CLI。 cli.spec.ts 通过 execaCommandSync 以子进程方式执行 node <CLI_PATH> <args>,并设置环境变量 _VITE_TEST_CLI=true。源码中的 installstart 检测到该变量后会跳过真实安装/启动、仅打印 (skipped in test)src/index.ts#L414-L438),从而让 20 余个端到端用例(交互提示、无效模板、目录冲突、文件清单比对、标题替换等)能在 CI 中稳定运行。

构建产物。 包的可执行入口是 index.js(仅两行,import './dist/index.js'),由 tsdown.config.tsnode20 为目标从 src/index.ts 构建,且构建时会把各模板目录的 CC0 许可证文本合入 LICENSE 说明。包同时注册了 create-vitecva 两个 bin 名。

八、社区模板:tiged 用法

README 指出 create-vite 的定位是“为流行框架快速起步的基础模板工具”;对于其他工具链或框架,官方建议参考 Awesome Vite 社区的社区维护模板清单,并使用 tiged 这类工具按 user/project 形式拉取:

npx tiged user/project my-project
cd my-project

npm install
npm run dev

这一方式与 create-vite 内部对外部模板(如 RSC starter)的处理思路一致——本质上都是“按仓库模板复制 + 后续安装启动”。

小结:一条命令背后的完整链路

综合源码可以总结出 create-vite 的完整链路:mri 解析参数 → TTY / --interactive 决定交互级别 → Agent 环境提示 → 目录与包名规范化(非法字符清洗、合法性校验)→ 非空目录三选一处置(保留 .git)→ 内置模板目录复制(点文件重命名 + index.html 标题与 package.json 名称替换)→ 变体后置改造(React Compiler 插件注入 / ESLint 平替 Oxlint)→ 按包管理器执行安装与 dev

理解这条链路后,你在日常使用中可以更放心地:用 -t 精确指定模板、用 . 在现有目录内重搭、用 --overwrite 处理非空目录、用 --no-interactive 写进脚本或交给 Agent 执行,并通过 packages/create-vite/tests/cli.spec.ts 中的断言核对任何一步的预期行为。

登录后查看全文
热门项目推荐
相关项目推荐