VITE构建基础项目模板

  1. 终端执行命令npm init vite@latest新建项目,选择Vue+Typescript
  2. 之后cd进入项目文件夹执行npm install则本步骤完成

环境变量配置优化

  1. 在项目根目录下新建env文件加存放不同环境需求下的环境变量信息:.env文件、.env.development文件、.env.production文件……对于更大的项目可能还有测试环境下的环境变量文件
  • .env公共的环境变量信息
  • .env.production生产环境下的环境变量信息
  • .env.development开发环境下的环境变量信息

注意:

  1. 因为是新建env文件夹,所以需要在vite.config.ts文件中的config对象中添加envDir: ‘env’
  2. 对于环境变量文件中的环境变量名必须以VITE开头,否则需要额外说明
  1. 在package.json添加命令"dev-prod": "vite serve --mode production"可用来测试生产环境下的环境变量文件

优化生产构建后console和debugger关闭

  1. 在vite.config.ts文件中的config对象中添加以下内容
1
2
3
4
5
6
7
8
9
10
build: {
// 如果出现npm run build失败可能需要安装一下terser:npm i terser -D
minify: "terser",
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
}

注意:如果build构建后的用于测试,可能测试环境下需要console等,就参考下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { defineConfig, loadEnv } from 'vite'
// https://vitejs.dev/config/

export default defineConfig(({ command, mode, ssrBuild }) => {
const env = loadEnv(mode, `${process.cwd()}/env`, '')
// 为什么要这样做,是为了 process.env和mode一致性
Object.assign(process.env, env, { NODE_ENV: mode })
return {
mode,
...
build: {
minify: "terser", // 必须开启:使用 terserOptions 才有效果
terserOptions: {
compress: {
drop_console: process.env.NODE_ENV === 'production' ? true : false,
drop_debugger: process.env.NODE_ENV === 'production' ? true : false,
},
},
}
}
})


优化文件引用路径

  1. 在vite.config.ts文件的config对象添加下列代码
1
2
3
4
5
6
7
import {resolve} from "path"; // 需要import
// 下面代码加入config对象中
resolve: {
alias: {
"@": resolve(__dirname, 'src')
}
},
  1. 如果添加上述代码后发现使用@方式引入组件依然报错,则在vite-env.d.ts文件中添加下列代码
1
2
3
4
5
6
declare module '*.vue' {
import type {DefineComponent} from 'vue';

const component: DefineComponent<{}, {}, any>;
export default component;
}

配置CSS全局变量

  1. 使用scss作为css预处理器,先安装相关依赖
1
npm i sass sass-loader --save-dev
  1. 对于一些全局css变量可以在src下建立全局css文件global.scss,然后在vite.config.js文件中的config对象添加配置
1
2
3
4
5
6
7
8
css: {
// css预处理器
preprocessorOptions: {
scss: {
additionalData: '@import "@/assets/style/global.scss";'
}
}
}

路由vue-router配置

  1. 安装依赖
1
npm install vue-router@4
  1. 在src文件夹下新建router文件下,并在router文件夹下新建index.ts,内容如下,然后记得在main.ts挂载到app之前添加use(router)
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
import {createRouter, createWebHashHistory} from 'vue-router'
import HomeView from '@/views/HomeView.vue'

const routes = [
{
path: '/',
name: 'Home',
component: HomeView
},
// 无匹配页面则跳转到404
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('@/views/NotFoundView.vue')
}
]

const router = createRouter(
{
history: createWebHashHistory(),
routes: routes,
// 在导航栏中,为当前活动路由的菜单项添加类名
linkActiveClass: 'router-active'
}
)

export default router

说明:在组件内部可以通过 useRouter()useRoute() 来访问路由器实例和当前路由

  1. 在router文件下创建createRouteGuards.ts用作全局路由守卫配置,并在router/index.ts里面export router之前调用createRouteGuards(router)
1
2
3
4
5
6
7
8
import {Router} from "vue-router";

export const createRouteGuards = (router: Router) => {
// @ts-ignore
router.beforeEach(async (to, from, next) => {
next()
})
}

状态管理库Pinia配置

  1. 老规矩先安装依赖,后面是持久化插件(保证页面刷新的时候缓存不会刷新
1
npm install pinia pinia-plugin-persistedstate
  1. 在src下面新建文件夹store,再新建文件index.ts,代码如下,然后记得在main.ts挂载到app之前添加use(store)
1
2
3
4
5
6
7
8
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const store = createPinia()
// 使用持久化插件
store.use(piniaPluginPersistedstate)

export default store
  1. 可能状态管理可能会分模块,比如用户认证相关、平台基本信息相关,因此可以在store文件夹下新建modules文件夹,每个不同模块一个单独的ts文件,比如下面的useUserStore.ts(一般以use开头),具体使用参考Home | Pinia 中文文档 (web3doc.top)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { defineStore } from "pinia";

export const useUserStore = defineStore('user', {
// 推荐使用完整类型推断的箭头函数
state: () => {
return {
username: '2aurora2',
counter: 0,
}
},
// 状态的计算值computed, 无法向它们传递任何参数; 但是,可以从 getter 返回一个函数以接受任何参数
getters: {
addCounter: (state) => {
return state.counter += 1;
}
},
// 相当于组件的methods
actions: {},
// 启用插件
persist: true
})

网络请求AXIOS配置

  1. 老规矩先安装对应依赖
1
npm install axios
  1. 将axios的相关配置和请求方式的封装写在src/utils/http下,新建instance.ts文件和service.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
49
// instance.ts
import axios from 'axios'

const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_PROXY_URL,
timeout: 10 * 1000,
headers: {
'Content-Type': 'application/json',
}
})

// 请求拦截器
axiosInstance.interceptors.request.use(
(config) => {
return config;
},
(err) => {
return Promise.reject(err);
}
)

// 响应拦截器
// 2xx 范围内的状态码都会触发该函数
axiosInstance.interceptors.response.use(
(response) => {
return response;
},
(err) => {
return Promise.reject(err);
}
)

export default axiosInstance;

// service.ts
import axiosInstance from "./instance.js";

const get = (url: string) => {
return axiosInstance.get(url);
}

const post = (url: string, data?: Object) => {
return axiosInstance.post(url, data);
}

export default {
get,
post
}
  1. 所有与后端交互的接口信息在src文件夹下另开一个文件夹api,api文件夹下新建index.ts文件、type.ts文件和不同模块文件夹
  • index.ts导出不同模块的相关接口
1
2
3
4
5
import userApi from './user'

export default {
userApi, // 用户相关API
}
  • type.ts定义一些公共类型,如后端的返回值类型
1
2
3
4
5
export type ResponseResult<T> = {
code: number;
message: string;
data: T;
}
  • 分模块文件夹代表一个模块,每个模块文件夹下均为index.ts和type.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
// api/user/index.ts
import service from "@/utils/http/service.ts";
import {ResponseResult} from "@/api/type.ts";
import {LoginReqType, LoginResType} from "@/api/user/type.ts";

const login = (data: LoginReqType) => {
return service.post<ResponseResult<LoginResType>>('/user/login' +
'?email=' + data.email +
'&password=' + data.password, data)
}

export default {
login, // 用户登录
};

// api/user/type.ts
export type LoginReqType = {
email: string;
password: string;
}

export type LoginResType = {
token: string;
expirationTime: string;
}

其他配置

  1. 在src下新建types/index.ts用来描述全局自定义类型export type……
  2. 在src下新建const/index.ts用来定义常量,将常量定义在一个对象里面然后导出
1
2
3
4
export const CONST = {
PI: 3.14159,
GRAVITY: 9.81,
}

后续如果有其他会继续补充……