引言
新建一个前端项目的瞬间,开发者通常面临两难:手动搭脚手架要面对「配置地狱」,而全盘依赖模板又容易得到一个难以维护的黑盒。Vite 的 create-vite 提供了一条中间路径——它足够快、足够小,生成的骨架几乎无配置即可运行,同时又足够透明,让开发者可以一步步理解并改造它。
本文从 npm create vite 讲起,带你走过从脚手架到可维护工程的完整路径:模板选择、目录结构、依赖管理、代码质量工具链(ESLint / Prettier / Husky / lint-staged)、路径别名,以及团队协作规范。读完你将能独立初始化一个「拿来即用、改得明白」的 Vite 工程。
前置:Node.js 18+、npm/pnpm 基础。构建工具的底层原理可结合 https://plumephp.com/frontend-vite-deep-dive/ 一并阅读。
目录
- 1. 为什么选择 create-vite
- 2. 初始化项目:模板与交互
- 3. 目录结构解剖
- 4. 依赖管理与脚本设计
- 5. 代码质量工具链
- 6. 路径别名与基础配置
- 7. 从模板到工程:演进路径
- 8. 团队协作规范
- 9. 总结:脚手架的取舍
- 延伸阅读
1. 为什么选择 create-vite
1.1 对比传统脚手架
| 方案 | 启动速度 | 配置透明度 | 生态契合 |
|---|---|---|---|
| create-vite | 秒级 | 极高(几乎零配置) | React/Vue/Svelte/Solid 官方推荐 |
| CRA(已退役) | 分钟级 | 低(黑盒 react-scripts) | 仅 React |
| create-next-app | 秒级 | 中 | 仅 Next.js 全栈 |
| 手动搭建 | 取决于经验 | 极高 | 完全可控 |
1.2 create-vite 的核心取舍
- 非开箱即用全家桶:只生成最小可运行骨架,不强制 eslint/prettier(你可自行加入)。
- 模板即源码:生成的代码是你可以逐行读懂、按需修改的普通工程。
- 与框架深度绑定:官方模板针对各框架做了开箱优化(如 React Fast Refresh、Vue HMR)。
1.3 什么时候不用它
大型企业级多包仓库、需要复杂代码生成的项目,直接以空目录 + 手动配置或基于公司内部脚手架模板起步,往往更合适。
2. 初始化项目:模板与交互
2.1 一条命令启动
# npm
npm create vite@latest my-app -- --template react-ts
# 或交互式选择
npm create vite@latest my-app
# pnpm / yarn
pnpm create vite my-app --template vue-ts
yarn create vite my-app --template svelte-ts
2.2 官方模板一览
| 模板 | 适用场景 | 备注 |
|---|---|---|
vanilla | 原生 JS/TS 实验 | 最小骨架 |
react / react-ts | React 应用 | Fast Refresh 开箱 |
vue / vue-ts | Vue 3 应用 | 含 <script setup> 示例 |
svelte / svelte-ts | Svelte | SvelteKit 的轻量替代 |
solid / solid-ts | SolidJS | 细粒度响应式 |
lit | Web Components | Lit 框架 |
2.3 交互式选择的内核
framework? ──> react | vue | svelte | solid | vanilla | lit | ...
variant? ──> plain | TypeScript | TS+SWC | 框架特定变体
交互式流程本质上就是在做「模板名拼接」——选择完成后,create-vite 从本地模板缓存解压对应骨架,不产生网络下载框架源码的等待。
3. 目录结构解剖
3.1 生成的默认结构(react-ts 模板)
my-app/
├── public/ # 静态资源,原样拷贝到产物根
│ └── vite.svg
├── src/
│ ├── assets/ # 需要构建处理的资源(会被 hash)
│ ├── App.css
│ ├── App.tsx
│ ├── index.css
│ ├── main.tsx # 应用入口
│ └── vite-env.d.ts # Vite 客户端类型声明
├── .gitignore
├── index.html # 唯一的 HTML 入口(位于根而非 public)
├── package.json
├── tsconfig.json # 项目引用结构
├── tsconfig.app.json
├── tsconfig.node.json # 针对 vite.config 的 Node 环境配置
└── vite.config.ts # Vite 配置文件
3.2 为什么 index.html 在根目录
这是 Vite 区别于 webpack 的关键设计:index.html 是应用入口,<script type="module" src="/src/main.tsx"> 声明入口模块。Vite 通过分析 HTML 中的模块引用,建立模块图(module graph),开发期按需编译、生产期以它为起点打包。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
3.3 public 与 src/assets 的区别
| 存放位置 | 处理方式 | 适用 |
|---|---|---|
public/ | 原样拷贝,URL 以 / 开头 | favicon、robots.txt、无法 hash 的文件 |
src/assets/ | 走构建管线,自动 hash + 压缩 | 图片、字体等被引用的资源 |
4. 依赖管理与脚本设计
4.1 package.json 的核心脚本
{
"name": "my-app",
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"lint": "eslint ."
},
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@types/react": "^19.0.0",
"@vitejs/plugin-react": "^4.3.0",
"typescript": "~5.6.0",
"vite": "^6.0.0"
}
}
4.2 三个关键脚本的作用域
| 脚本 | 命令 | 作用 |
|---|---|---|
dev | vite | 启动开发服务器(默认 5173 端口) |
build | tsc -b && vite build | 类型检查 + 生产构建到 dist/ |
preview | vite preview | 本地预览构建产物(模拟生产服务器) |
4.3 为什么是 "type": "module"
Vite 6 及其配置都要求 ESM。"type": "module" 让 .js 文件默认按 ESM 解析,vite.config.ts 中的 import/export 语法才能正常工作,也是现代前端工程的事实标准。
5. 代码质量工具链
脚手架默认不含 lint/format,但工程化项目几乎必然要加。下面是经过验证的最小组合。
5.1 ESLint + Prettier + Husky + lint-staged
npm install -D eslint @eslint/js typescript-eslint prettier eslint-config-prettier husky lint-staged
5.2 精简 eslint.config.js
import js from '@eslint/js'
import tseslint from 'typescript-eslint'
import prettier from 'eslint-config-prettier'
export default tseslint.config(
{ ignores: ['dist', 'node_modules'] },
js.configs.recommended,
...tseslint.configs.recommended,
prettier, // 关闭与 Prettier 冲突的规则
{
rules: {
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
},
},
)
5.3 提交前强制检查(Husky + lint-staged)
npx husky init
# 生成 .husky/pre-commit,内容:
npx lint-staged
// package.json
{
"lint-staged": {
"*.{js,ts,jsx,tsx}": ["eslint --fix", "prettier --write"]
}
}
5.4 工作流
git add . -> pre-commit 钩子 -> lint-staged 只检查暂存文件
-> eslint --fix 修复 -> prettier --write 格式化
-> 全部通过才允许 commit
6. 路径别名与基础配置
6.1 vite.config.ts 配置别名
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { fileURLToPath, URL } from 'node:url'
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
})
6.2 tsconfig 联动(避免 TS 报错)
// tsconfig.app.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
6.3 在代码中使用
// import { Button } from '../../components/Button'
// 变成
import { Button } from '@/components/Button'
别名避免了深层相对路径 ../../../ 的脆弱性,重构目录时不再需要大范围修改 import。
7. 从模板到工程:演进路径
7.1 模板只是起点
模板解决「跑起来」的问题,工程化解决「持续交付」的问题。演进通常分四步:
阶段1: 骨架可运行(模板自带)
阶段2: 代码规范落地(ESLint/Prettier/提交钩子)
阶段3: 目录分层(features / pages / components / hooks)
阶段4: 基础设施(路由、状态、请求层、CI/CD)
7.2 一个推荐的 src 分层
src/
├── api/ # 接口层:axios/fetch 封装
├── assets/ # 静态资源
├── components/ # 通用组件
├── features/ # 按业务域划分的功能模块
├── hooks/ # 自定义 hooks
├── layouts/ # 布局组件
├── pages/ # 路由页面
├── router/ # 路由配置
├── stores/ # 状态管理
├── types/ # 全局类型
├── utils/ # 工具函数
├── main.tsx
└── App.tsx
7.3 渐进式改造而非推倒重来
模板提供的 App.tsx 示例可以直接删除、替换为真实业务入口;vite.config.ts 按需增量添加插件。保持「最小改动」原则,避免一开始就堆砌大量脚手架配置。
8. 团队协作规范
8.1 版本锁定
# 锁定依赖版本,配合 lockfile
npm ci
pnpm install --frozen-lockfile
8.2 Node 版本统一
// .nvmrc
20
// package.json
{
"engines": {
"node": ">=20.0.0"
}
}
8.3 CI 基本检查(示意)
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'npm' }
- run: npm ci
- run: npm run lint
- run: npm run build
9. 总结:脚手架的取舍
9.1 核心收获
- create-vite 是最小可运行的透明骨架:秒级启动、零黑盒、逐行可读。
- index.html 在根目录是理解 Vite 模块图设计的钥匙。
- 工具链分层渐进落地:先跑起来,再加规范,再分层,再上 CI。
- 别名与类型联动解决的是长期可维护性问题。
9.2 自检清单
| 检查项 | 是否掌握 |
|---|---|
| 能用不同模板初始化项目 | ☐ |
| 能解释 public 与 src/assets 区别 | ☐ |
| 能独立配置 ESLint/Prettier/Husky | ☐ |
| 能配置并解释路径别名 | ☐ |
| 能设计团队提交规范 | ☐ |
9.3 下一步
读 https://plumephp.com/vite-config-guide/ 深入配置项,或直接进入 https://plumephp.com/vite-plugin-development/ 编写你的第一个插件。
延伸阅读
- https://plumephp.com/frontend-vite-deep-dive/ — Vite 预构建与 HMR 的底层实现
- https://plumephp.com/vite-config-guide/ — defineConfig 全参数详解
- https://plumephp.com/vite-build-optimization/ — 生产构建优化
- create-vite 官方文档 — 完整模板与命令参考
- Vite 中文文档
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。