# Vite相关使用

## .env文件

### 文件名简介

- `.env`：公用配置文件
- `.env.development`：开发环境配置
- `.env.production`：生产话就配置

### 修改环境前缀

在配置文件中加上`envPrefix`

```ts
export default defineConfig(
	(): UserConfig => ({
		envPrefix: 'BUNNY',
	}),
);
```

## 使用gzip

安装

```sh
npm i vite-plugin-compress
```

需要文件中引入

```js
import compress from 'vite-plugin-compress';

export default {
	plugins: [compress()],
};
```

## 动态加载路由

```ts
import { routeFilenameHelper } from '@/utils/file/routeFileUtil';
import _ from 'lodash';
import { RouteRecordRaw } from 'vue-router';

// * 最终路由
const routeMap: Record<string, RouteRecordRaw> = {};

// * 所有处理的路由
const contexts = [
	{ context: import.meta.glob('@/views/**/index.vue', { eager: true, import: 'default' }), isIndex: true },
	{ context: import.meta.glob('@/views/**/page.ts', { eager: true, import: 'default' }), isIndex: false },
];

/**
 * 构建路由信息
 * @param context 上下文信息
 * @param isIndex 是否第一次遍历
 * @param route 路由内容
 */
function buildRouteTree(context: any, isIndex: boolean, route: any) {
	// 遍历当前子路由
	Object.entries(context).forEach(([filePath, _]) => {
		// 获取子路由下所有文件对象格式
		const childrenFileInfo = routeFilenameHelper(filePath);
		// 组装子路由对象
		const childrenRoute: any = {
			name: childrenFileInfo?.name,
			path: childrenFileInfo!.path,
			component: isIndex ? context[filePath] : undefined,
			children: [],
			meta: { isFullScreen: false },
		};
		// 如果当前路由对象等于当前遍历的路由子对象，将子路由推到父级路由中
		if (childrenFileInfo?.path.includes(route.path) && childrenFileInfo?.path !== route.path) {
			route.children.push(childrenRoute);
		}
	});
}

/**
 * 遍历路由信息
 * @param context 路由上下文
 * @param isIndex 是否为索引遍历
 */
const createRouteList = (context: any, isIndex: boolean) => {
	Object.entries(context).forEach(([filePath, exportRouteConfig]) => {
		const fileInfo = routeFilenameHelper(filePath);
		// 组装路由对象
		const route: any = {
			name: fileInfo?.name,
			path: fileInfo!.path,
			component: isIndex ? context[filePath] : undefined,
			children: [],
			meta: { isFullScreen: false },
		};

		// 初始化赋值
		if (isIndex) {
			routeMap[route.path] = route;
			buildRouteTree(context, isIndex, route);
		} else {
			// 导出当前存在的路由并重新赋值
			const existingRoute = routeMap[route.path];
			// 当前路由存在
			if (existingRoute) {
				// 使用loadsh合并对象
				routeMap[route.path] = _.merge(existingRoute, exportRouteConfig);
			}
		}
	});
};

// * 生成路由信息
contexts.forEach(({ context, isIndex }) => createRouteList(context, isIndex));

export const pageRoutes: Array<RouteRecordRaw> = Object.values(routeMap);
```

> 需要注意的是，为了动态导入生产环境也可以运行，需要`context[filePath]`需要使用这段话，才可以

## 输出环境变量内容

```ts
console.log(import.meta.env);
```

## 动态加载CDN

在Module中配置相关内容，相关文档查看：https://www.npmjs.com/package/vite-plugin-cdn-import

```ts
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import { defineConfig, UserConfig } from 'vite';
import cdn from 'vite-plugin-cdn-import';

export default defineConfig(
	(): UserConfig => ({
		plugins: [
			cdn({
				modules: [],
			}),
		],
	}),
);
```

> ```
> npm i vite-plugin-cdn-import
> ```

## 兼容老版本浏览器

在plugin中加入

```ts
legacy({ targets: ["defaults", "not IE 11"] }),
```

详细配置查看：https://www.npmjs.com/package/@vitejs/plugin-legacy

## 打包设置

如果打包中包含`node_module`包全部放到`vendor-[hash].js`中

![image-20240527152054024](./images/image-20240527152054024.png)

## 配置跨域

`process.env.BUNNY_APP_URL`设置在这三个文件中，读取是这三个配置

![image-20240527152136447](./images/image-20240527152136447.png)

```ts
server: {
  host: "0.0.0.0",
    port
:
  6261,
    open
:
  true,
    cors
:
  true,
    proxy
:
  {
    "/api"
  :
    {
      target: process.env.BUNNY_APP_URL,
        changeOrigin
    :
      true,
        rewrite
    :
      (path: string) => path.replace(/^\/api/, "/api")
    }
  ,
    "/mock"
  :
    {
      target: process.env.BUNNY_APP_URL,
        changeOrigin
    :
      true,
        rewrite
    :
      (path: string) => path.replace(/^\/mock/, "/mock")
    }
  }
}
,
```

## 配置JSX

项目中已经设置好了JSX相关功能

![image-20240527152316666](./images/image-20240527152316666.png)

## Mock和多语言

### Mock设置

在环境已经设置好了Mock，只需要在`/src/mock`中写代码即可。

### 多语言设置

多语言现在作为网络请求来发送，在pinia中设置本地持久存储。

后端需要按照返回格式进行传送

![image-20240527152545485](./images/image-20240527152545485.png)

发送请求和初始化放在`App.vue`中

![image-20240527153132792](./images/image-20240527153132792.png)

#### 多语言只做本地化

只需要在`i18n`中加入你的语言，之后在`index.ts`中引用即可

![image-20240527153316912](./images/image-20240527153316912.png)

格式大致如下

![image-20240527153421787](./images/image-20240527153421787.png)

#### 后端返回多语言格式

这个格式也可以改，默认的如下。需要包含默认语言`local:xxx`

```
{
    "i18n": {
        "zh_cn": {
            "login": {
                "reset": "重置",
                "register": "登录"
            },
            "home": {
                "articleModeAlbum": "相册模式",
                "articleModeList": "列表模式"
            },
            "tabs": {},
            "header": {
                "fullScreen": "全屏",
                "exitFullScreen": "退出全屏",
                "personalData": "个人信息",
                "changePassword": "修改密码",
                "logout": "退出登录"
            },
            "tip": {
                "loading": "加载中..."
            }
        },
        "en": {
            "login": {
                "reset": "reset",
                "register": "register"
            },
            "home": {
                "articleModeAlbum": "Album Mode",
                "articleModeList": "List Mode"
            },
            "tabs": {},
            "header": {
                "fullScreen": "Full Screen",
                "exitFullScreen": "Exit Full Screen",
                "personalData": "Personal Data",
                "changePassword": "Change Password",
                "logout": "Logout"
            },
            "tip": {
                "loading": "Loading..."
            }
        },
        "local": "zh_cn"
    }
}
```

### Vue指令

配置了打印、复制、水印等指令

![image-20240527153512670](./images/image-20240527153512670.png)
