Vue3 + Vite + Ant Design Vue + Axios + Pinia 脚手架搭建指南
下面是一个完整的 Vue3 项目脚手架配置,使用 TypeScript 编写,包含所有必要的配置文件和基础代码。
项目结构
text
my-vue-project/
├── public/
├── src/
│ ├── api/
│ ├── assets/
│ ├── components/
│ ├── layouts/
│ ├── router/
│ ├── stores/
│ ├── utils/
│ ├── views/
│ ├── App.vue
│ ├── main.ts
│ └── vite-env.d.ts
├── .env
├── .env.development
├── .env.production
├── .eslintrc.js
├── .gitignore
├── package.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
1. package.json
json
{
"name": "my-vue-project",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
},
"dependencies": {
"@ant-design/icons-vue": "^7.0.0",
"ant-design-vue": "^4.0.0",
"axios": "^1.6.2",
"pinia": "^2.1.7",
"vue": "^3.3.0",
"vue-router": "^4.2.5"
},
"devDependencies": {
"@types/node": "^20.10.0",
"@vitejs/plugin-vue": "^4.5.0",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^11.0.3",
"eslint": "^8.55.0",
"eslint-plugin-vue": "^9.17.0",
"prettier": "^3.1.0",
"typescript": "^5.3.0",
"vite": "^5.0.0",
"vue-tsc": "^1.8.11"
}
}
2. vite.config.ts
typescript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
server: {
port: 3000,
open: true,
cors: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^/api/, '')
}
}
},
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
modifyVars: {
'primary-color': '#1890ff',
'link-color': '#1890ff',
'border-radius-base': '4px'
}
}
}
}
})
3. tsconfig.json
json
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": [
"ESNext",
"DOM"
],
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
}
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue"
]
}
4. .env 文件
.env (通用环境变量)
text
VITE_APP_TITLE=My Vue App
VITE_APP_BASE_API=/api
.env.development (开发环境)
text
NODE_ENV=development
VITE_APP_ENV=development
VITE_APP_BASE_URL=http://localhost:3000
.env.production (生产环境)
text
NODE_ENV=production
VITE_APP_ENV=production
VITE_APP_BASE_URL=https://production.example.com
5. 源代码文件
src/main.ts
typescript
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/reset.css'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(Antd)
app.mount('#app')
src/vite-env.d.ts
typescript
/// <reference types="vite/client" />
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_APP_BASE_API: string
readonly VITE_APP_BASE_URL: string
readonly VITE_APP_ENV: 'development' | 'production'
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
src/App.vue
vue
<template>
<a-config-provider>
<router-view />
</a-config-provider>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'App'
})
</script>
<style>
#app {
height: 100vh;
}
</style>
src/router/index.ts
typescript
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import('@/views/AboutView.vue')
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
export default router
src/stores/index.ts (Pinia store)
typescript
import { defineStore } from 'pinia'
interface AppState {
count: number
}
export const useAppStore = defineStore('app', {
state: (): AppState => ({
count: 0
}),
getters: {
doubleCount: (state) => state.count * 2
},
actions: {
increment() {
this.count++
},
decrement() {
this.count--
}
}
})
src/api/index.ts (Axios封装)
typescript
import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { message } from 'ant-design-vue'
const service: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 10000
})
// 请求拦截器
service.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 在这里可以添加token等
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
(response: AxiosResponse) => {
const res = response.data
if (res.code !== 200) {
message.error(res.message || 'Error')
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
(error) => {
message.error(error.message || 'Error')
return Promise.reject(error)
}
)
export default service
src/views/HomeView.vue
vue
<template>
<a-layout>
<a-layout-header>
<h1>{{ title }}</h1>
</a-layout-header>
<a-layout-content>
<div class="content">
<a-button type="primary" @click="handleIncrement">Increment</a-button>
<span class="count">Count: {{ count }}</span>
<span class="double-count">Double Count: {{ doubleCount }}</span>
<a-button @click="handleDecrement">Decrement</a-button>
</div>
</a-layout-content>
</a-layout>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue'
import { useAppStore } from '@/stores'
import { message } from 'ant-design-vue'
export default defineComponent({
name: 'HomeView',
setup() {
const store = useAppStore()
const title = import.meta.env.VITE_APP_TITLE
const count = computed(() => store.count)
const doubleCount = computed(() => store.doubleCount)
const handleIncrement = () => {
store.increment()
message.success('Incremented!')
}
const handleDecrement = () => {
store.decrement()
message.warning('Decremented!')
}
return {
title,
count,
doubleCount,
handleIncrement,
handleDecrement
}
}
})
</script>
<style scoped>
.content {
padding: 24px;
text-align: center;
}
.count,
.double-count {
display: inline-block;
margin: 0 16px;
font-size: 18px;
}
</style>
src/views/AboutView.vue
vue
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'AboutView'
})
</script>
6. .gitignore
text
.DS_Store
node_modules
/dist
.env.local
.env.*.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
使用说明
- 安装依赖:
bash
npm install
- 运行开发服务器:
bash
npm run dev
- 构建生产版本:
bash
npm run build
- 预览生产版本:
bash
npm run preview
这个脚手架包含了:
- Vue 3 组合式API
- Vite 构建工具
- Ant Design Vue UI组件库
- Pinia 状态管理
- Axios HTTP客户端
- TypeScript 支持
- 环境变量配置
- 路由配置
- 基本的布局和组件
你可以根据需要进一步扩展这个基础结构。
额外建议
- 可以添加ESLint和Prettier进行代码规范
- 考虑添加Husky和lint-staged进行Git提交前检查
- 可以配置Mock.js进行接口模拟开发
- 考虑添加VueUse库提供更多实用的组合式API
希望这个脚手架对你的项目有所帮助!