为什么写这篇:2023 年 Vue 3 + Vite + TypeScript 已经是新项目"标准三件套"。本文走通从 npm create vite 到生产环境打包的完整流程,把代码片段 / ESLint / Prettier / 路径别名 / 多环境变量 / 代理一次性配齐。
适用读者:Vue 3 初学者;从 Vue 2 迁过来的工程师;想用 Vite 替代 Webpack 的项目负责人。
前置知识:会用 npm;了解 Vue / TypeScript 基础。
目录
- 环境要求
- 两种创建项目方式
- 项目目录结构
- IDE 工具与 VSCode 插件
- 代码片段配置
- Vite 配置:路径别名 + 代理 + 端口
- 代码风格:ESLint + Prettier
- 多环境变量配置
- 常见工程化依赖
- TS2307 找不到 .vue 类型
1. 环境要求
| 工具 | 版本 | 备注 |
|---|
| Node.js | 20.12.0+(推荐 LTS) | Vite 5 要求 Node 18+ 或 20+ |
| npm | 10+ | Node 自带 |
| pnpm | 8+(推荐) | 装包快、磁盘省 |
| Vite | 5.3+ | 本文以 Vite 5 为准 |
| VSCode | 最新版 | 装 Vue 官方插件 |
Vite 7(2025 推出) 要求 Node 20.19+ 或 22.12+。
1
2
3
| node -v # v20.12.0
npm -v # 10.x
pnpm -v # 8.x
|
2. 两种创建项目方式
方式一:npm create vite@latest(推荐)
交互式:
1
2
3
4
5
| ✔ Project name: … vue3-ts-demo
✔ Select a framework: › Vue
✔ Select a variant: › TypeScript
✔ Use rolldown-vite (Experimental)?: no # 实验性质,暂不用
✔ Install with pnpm and start now?: yes
|
完成后 Vite 自动启动:
1
2
3
4
5
| VITE v5.3.5 ready in 339 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
|
Rolldown-Vite:Vite 团队基于 Rust 的下一代打包器,目前实验阶段。生产环境建议关闭。
方式二:npm init vue@latest(Vue 官方脚手架)
1
2
3
4
5
6
7
8
9
| ✔ Project name: … iip-frontend
✔ 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
|
区别:
create-vite 极简,只有 Vue + TScreate-vue 是 Vue 官方脚手架,可选 Router/Pinia/测试/格式化
完成后:
1
2
3
4
5
6
7
8
| cd iip-frontend
npm install
npm run format # Prettier 全量格式化
npm run dev
git init && git add -A && git commit -m "init"
git remote add origin <YOUR_REPO_URL>
git push -u origin master
|
3. 项目目录结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| vue3-ts-demo/
├── dist/ # 构建产物
├── node_modules/
├── public/ # 不参与构建的静态资源
│ └── vite.svg
├── src/
│ ├── assets/ # 静态资源(图片、字体)
│ ├── components/ # 公共组件
│ │ └── HelloWorld.vue
│ ├── router/ # vue-router 配置(若用 create-vue)
│ ├── stores/ # Pinia 状态
│ ├── views/ # 页面级组件
│ ├── App.vue # 根组件
│ ├── main.ts # 入口
│ ├── env.d.ts # 环境变量类型
│ └── vite-env.d.ts # Vite 内置类型
├── .env.development # 开发环境变量
├── .env.production # 生产环境变量
├── .eslintrc.cjs # ESLint 配置
├── .prettierrc.json # Prettier 配置
├── .gitignore
├── index.html # 入口 HTML
├── package.json
├── pnpm-lock.yaml # 必须提交
├── README.md
├── tsconfig.json # TS 根配置(references)
├── tsconfig.app.json # 应用代码 TS 配置
├── tsconfig.node.json # Node 环境 TS 配置
└── vite.config.ts # Vite 配置
|
tsconfig 的 references:Vite 模板默认拆成 tsconfig.app.json(业务代码)和 tsconfig.node.json(Vite 配置),用 references 关联。
4. IDE 工具与 VSCode 插件
4.1 必装插件
| 插件 | 用途 |
|---|
| Volar | Vue 3 + TS 官方语言服务(替代 Vetur) |
| TypeScript Vue Plugin (Volar) | TS 侧的 .vue 类型支持 |
| ESLint | 代码检查 |
| Prettier | 格式化 |
| EditorConfig for VS Code | 跨编辑器风格 |
| Auto Rename Tag | HTML 标签自动改名 |
| Path Intellisense | 路径补全 |
| Vue 3 Snippets | 代码片段 |
4.2 禁用 Vue 2 插件
如果之前装过 Vetur(Vue 2 时代的官方插件),必须禁用或卸载——它和 Volar 冲突,类型推断会乱。
5. 代码片段配置
.vscode/vue3.code-snippets:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| {
"Print to console": {
"prefix": "vue3",
"body": [
"<!-- ${1:new page} -->",
"<!-- @author: ${2:lwd} -->",
"<!-- @since: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE} -->",
"<!-- ${TM_FILENAME} -->",
"<template>",
" <div></div>",
"</template>",
"",
"<script setup lang=\"ts\">",
"</script>",
"",
"<style scoped>",
"</style>"
],
"description": "Vue 3 + TS 单文件组件模板"
}
}
|
输入 vue3 + Tab 即可生成 SFC 三段式骨架。
6. Vite 配置:路径别名 + 代理 + 端口
6.1 装 Node 类型声明
让 TS 知道 path.resolve、process.env 等 Node API。
6.2 tsconfig.node.json 加 types
1
2
3
4
5
6
7
| {
"compilerOptions": {
"types": ["node"],
"composite": true
},
"include": ["vite.config.ts"]
}
|
6.3 vite.config.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import * as path from 'path'
// https://vite.dev/config/
export default defineConfig({
resolve: {
// 路径别名
alias: {
'@': path.resolve(__dirname, 'src')
}
},
plugins: [vue()],
server: {
port: 8080, // 启动端口
host: '127.0.0.1', // 监听地址
open: true, // 自动打开浏览器
hmr: {
host: '127.0.0.1',
port: 8080
},
// 反向代理
proxy: {
'/api': {
target: 'https://your-backend.example.com',
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/api/, '')
}
}
},
// 生产构建
build: {
target: 'es2020',
sourcemap: false,
rollupOptions: {
output: {
manualChunks: {
// 把第三方库拆成单独 chunk
vue: ['vue', 'vue-router', 'pinia'],
echarts: ['echarts']
}
}
}
}
})
|
tsconfig.json 也要加别名(不然 TS 找不到 @/components/...):
1
2
3
4
5
6
7
8
| {
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
|
7. 代码风格:ESLint + Prettier
7.1 装依赖
1
| npm i -D eslint eslint-plugin-vue @typescript-eslint/parser @typescript-eslint/eslint-plugin
|
7.2 .eslintrc.cjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| module.exports = {
root: true,
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020,
sourceType: 'module',
ecmaFeatures: { jsx: true }
},
extends: [
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended'
],
rules: {
// 自定义规则...
}
}
|
7.3 .eslintignore
1
2
3
| node_modules/
dist/
index.html
|
7.4 package.json scripts
1
2
3
4
5
| {
"scripts": {
"eslint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src"
}
}
|
7.5 Prettier
1
| npm i -D prettier eslint-config-prettier eslint-plugin-prettier
|
.prettierrc.cjs:
1
2
3
4
5
6
7
8
9
10
11
12
| module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: false, // Vue 风格无分号
singleQuote: true,
quoteProps: 'as-needed',
trailingComma: 'all',
bracketSpacing: true,
arrowParens: 'always',
endOfLine: 'auto'
}
|
.eslintrc.cjs extends 末尾加 'plugin:prettier/recommended'(关掉与 prettier 冲突的规则)。
7.6 VSCode 保存自动格式化
.vscode/settings.json:
1
2
3
4
5
6
7
8
9
| {
"editor.formatOnSave": true,
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[vue]": {
"editor.defaultFormatter": "Vue.volar"
}
}
|
8. 多环境变量配置
Vite 默认只有 development 和 production 两套环境。要多套(如 dev / test / staging / prod),自己建文件:
1
2
3
4
| .env # 所有环境都加载
.env.development # npm run dev 加载
.env.test # npm run build:test 加载
.env.production # npm run build:prod 加载
|
8.1 .env.development
1
2
3
4
| # 必须 VITE_ 开头才能被 import.meta.env 识别
VITE_ENV = 'development'
VITE_APP_BASE_API = '/api'
VITE_APP_TITLE = '开发环境'
|
8.2 .env.production
1
2
3
| VITE_ENV = 'production'
VITE_APP_BASE_API = 'https://api.example.com'
VITE_APP_TITLE = '生产环境'
|
8.3 package.json scripts
1
2
3
4
5
6
7
8
9
| {
"scripts": {
"dev": "vite",
"build": "vue-tsc -b && vite build",
"build:test": "tsc --noEmit && vite build --mode test",
"build:prod": "tsc --noEmit && vite build --mode production",
"preview": "vite preview"
}
}
|
8.4 代码里读环境变量
1
2
| console.log(import.meta.env.VITE_APP_BASE_API)
console.log(import.meta.env.VITE_ENV)
|
注意:
- 自定义变量必须
VITE_ 开头(防止意外暴露服务端配置) import.meta.env 是 Vite 注入的,不在 process.env 里
9. 常见工程化依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 路由
pnpm add vue-router@4
# 状态管理
pnpm add pinia pinia-plugin-persist # 后者是持久化插件
# HTTP
pnpm add axios
pnpm add nprogress # 顶部进度条
pnpm add @types/nprogress -D
# UI 库
pnpm add element-plus @element-plus/icons-vue
# 工具
pnpm add dayjs lodash
pnpm add @types/lodash -D
|
9.1 Pinia 持久化示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| // store/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
token: '',
name: ''
}),
actions: {
setToken(token: string) {
this.token = token
}
},
persist: {
key: 'user-store',
storage: localStorage
}
})
|
9.2 Axios 封装示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| // utils/http.ts
import axios from 'axios'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
NProgress.configure({ showSpinner: false })
const http = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 15000
})
http.interceptors.request.use(config => {
NProgress.start()
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
http.interceptors.response.use(
response => {
NProgress.done()
return response.data
},
error => {
NProgress.done()
return Promise.reject(error)
}
)
export default http
|
10. TS2307 找不到 .vue 类型
错误信息:
1
| error TS2307: Cannot find module './App.vue' or its corresponding type declarations.
|
解法:建 src/vite-env.d.ts(Vite 模板已自动生成):
1
2
3
4
5
6
7
| /// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
|
Why:.vue 不是原生模块,需要 TS 知道它的"形状"。DefineComponent 是 Vue 3 提供的 SFC 类型。
小结
Vue 3 + Vite + TS 工程化核心要点:
- 创建:
npm create vite@latest 选 Vue + TS 模板,30 秒跑通 demo - 目录:用
src/views、src/components、src/router、src/stores 标准化 - 配置:
vite.config.ts 配 alias / proxy / port,tsconfig.json 配 paths - 代码风格:ESLint + Prettier 双管齐下,保存自动格式化
- 环境变量:
VITE_ 前缀 + 多文件(.env.development / .env.production) - HTTP:Axios 拦截器 + NProgress 进度条 + 401 自动跳登录
下一步:学 Vue 3 专属特性——Composition API、<script setup>、Pinia 持久化、Suspense、<Teleport>、Volar 类型推断、Vitest 单元测试。Vue 3 + Vite 是 2024+ 的新项目默认选择。
参考资料