第 112 章:Vite 环境搭建
学习目标
- 理解 Vite 的核心优势
- 掌握 Vite + Vue 3 + TS 项目搭建
- 学会项目目录结构与基础配置
- 能用 create-vue 脚手架快速初始化项目
一、为什么选 Vite
Vite 是 Vue 3 官方推荐的构建工具,基于原生 ES Modules + esbuild。
1.1 Vite vs Webpack
| 维度 | Vite | Webpack |
|---|---|---|
| 启动速度 | ⚡ 极快(秒级) | 🐢 较慢(10s+) |
| HMR 热更新 | ⚡ 毫秒级 | 🐢 秒级 |
| 构建速度 | ⚡ 快(esbuild) | 🐢 较慢 |
| 配置复杂度 | 🟢 简单 | 🔴 复杂 |
| 生态 | 🟡 较新但完善 | 🟢 成熟 |
1.2 Vite 的核心原理
- 开发时:基于浏览器原生 ES Module,按需编译,不做 bundle
- 生产时:用 Rollup 打包,产出优化后的静态资源
二、环境准备
2.1 安装 Node.js
bash
# 检查版本(要求 ≥ 18.0.0)
node -v
npm -v
# 推荐使用 nvm 管理多版本
nvm install 18
nvm use 182.2 包管理器选择
| 工具 | 特点 |
|---|---|
| npm | Node.js 内置,默认选择 |
| yarn | 经典,Facebook 出品 |
| pnpm | 推荐,磁盘高效,速度快 |
| bun | 新兴,Zig 写的极速运行时 |
推荐使用 pnpm:
bash
# 安装 pnpm
npm install -g pnpm
# 设置源(国内加速)
pnpm config set registry https://registry.npmmirror.com三、创建项目
3.1 方式 1:create-vue 官方脚手架
bash
# 创建项目
pnpm create vue@latest
# 交互选项:
# ✔ Project name: my-vue-app
# ✔ Add TypeScript? Yes
# ✔ Add JSX Support? No
# ✔ Add Vue Router? Yes
# ✔ Add Pinia? Yes
# ✔ Add Vitest? No
# ✔ Add an End-to-End Testing Solution? No
# ✔ Add ESLint? Yes
# ✔ Add Prettier? Yes
cd my-vue-app
pnpm install
pnpm dev3.2 方式 2:手动搭建(学习推荐)
bash
# 1. 创建目录
mkdir my-vue-app && cd my-vue-app
# 2. 初始化 package.json
pnpm init
# 3. 安装依赖
pnpm add vue
pnpm add -D vite @vitejs/plugin-vue vue-tsc typescript3.3 最小化项目结构
my-vue-app/
├── index.html
├── package.json
├── vite.config.ts
├── tsconfig.json
├── tsconfig.node.json
└── src/
├── main.ts
├── App.vue
└── env.d.ts四、关键文件配置
4.1 package.json
json
{
"name": "my-vue-app",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc -b && vite build",
"preview": "vite preview",
"type-check": "vue-tsc --noEmit"
},
"dependencies": {
"vue": "^3.4.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.0",
"typescript": "~5.4.0",
"vite": "^5.2.0",
"vue-tsc": "^2.0.0"
}
}4.2 vite.config.ts
typescript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'node:path';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
server: {
port: 5173,
host: '0.0.0.0', // 允许局域网访问
open: true // 自动打开浏览器
},
build: {
target: 'es2020',
outDir: 'dist',
sourcemap: false,
chunkSizeWarningLimit: 1500
}
});4.3 tsconfig.json
json
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"noEmit": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"types": ["vite/client"]
},
"include": ["src/**/*", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}4.4 tsconfig.node.json
json
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "Bundler",
"allowSyntheticDefaultImports": true,
"strict": true
},
"include": ["vite.config.ts"]
}4.5 index.html
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Vue App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>4.6 src/env.d.ts
typescript
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const component: DefineComponent<{}, {}, any>;
export default component;
}4.7 src/main.ts
typescript
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');4.8 src/App.vue
vue
<script setup lang="ts">
import { ref } from 'vue';
const count = ref(0);
</script>
<template>
<div class="app">
<h1>Hello Vue 3 + Vite</h1>
<button @click="count++">count is: {{ count }}</button>
</div>
</template>
<style scoped>
.app {
text-align: center;
margin-top: 60px;
}
</style>五、运行与构建
5.1 开发模式
bash
pnpm dev
# 输出:
# VITE v5.2.0 ready in 230 ms
# ➜ Local: http://localhost:5173/
# ➜ Network: http://192.168.1.100:5173/5.2 生产构建
bash
pnpm build
# 输出:
# ✓ built in 2.5s
# dist/index.html 0.46 kB
# dist/assets/index-abc123.css 1.23 kB
# dist/assets/index-def456.js 52.10 kB5.3 预览构建产物
bash
pnpm preview六、推荐开发工具
6.1 VSCode 必备插件
| 插件 | 作用 |
|---|---|
| Volar | Vue 3 官方推荐(替代 Vetur) |
| TypeScript Vue Plugin | TS 类型支持 |
| ESLint | 代码规范 |
| Prettier | 代码格式化 |
| Vue VSCode Snippets | 代码片段 |
6.2 推荐的 settings.json
json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"typescript.tsdk": "node_modules/typescript/lib"
}七、常见问题
7.1 找不到 vue 模块
bash
# 错误: Cannot find module 'vue'
# 解决:
pnpm install vue7.2 .vue 文件报红
bash
# 错误: .vue 文件 TypeScript 报错
# 解决: 确保 src/env.d.ts 中有:
declare module '*.vue' { ... }7.3 端口被占用
typescript
// vite.config.ts
server: {
port: 5174, // 换一个
strictPort: false // 自动尝试下一个可用端口
}7.4 路径别名不生效
typescript
// vite.config.ts
import path from 'node:path';
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
}json
// tsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["src/*"]
}
}
}提示
Vite 配置和 TS 配置都需要设置别名,二者缺一不可。
八、实战:从 0 搭建一个完整项目
bash
# 1. 创建
pnpm create vue@latest my-app
cd my-app
# 2. 安装
pnpm install
# 3. 添加常用依赖
pnpm add vue-router pinia axios
pnpm add -D @types/node tailwindcss postcss autoprefixer
pnpm add @vueuse/core
# 4. 初始化 Tailwind
npx tailwindcss init -p
# 5. 启动
pnpm dev九、本章小结
| 要点 | 关键 |
|---|---|
| 构建工具 | Vite 5.x |
| 包管理器 | pnpm 推荐 |
| 脚手架 | create-vue |
| 入口文件 | index.html + src/main.ts |
| 路径别名 | vite.config.ts + tsconfig.json 都配置 |
| 开发命令 | pnpm dev |
| 构建命令 | pnpm build |
动手练习
- 创建项目:用
create-vue创建一个完整项目,包含 TS + Router + Pinia - 手动搭建:不用脚手架,手动从 0 搭建一个最小 Vue 3 项目
- 路径别名:配置
@/指向src/,验证生效 - VSCode 配置:安装 Volar,验证
.vue文件有 TS 类型提示
推荐阅读
- 📖 Vite 官方文档 — 中文文档
- 📖 create-vue — 官方脚手架
- 📖 Volar 文档 — Vue 3 IDE 支持
- 🌐 Awesome Vue 3 — 资源汇总
下一章:第 113 章:第一个 Vue 应用 →