You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
4.0 KiB
TypeScript

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
// @ts-expect-error process is a nodejs global
const host = process.env.TAURI_DEV_HOST;
const APP_NAME = "call-client";
const CONFIG_FILE_NAME = "config.json";
const API_QUEUE_CALLER_PATH = "/api/queue/caller";
const DEFAULT_API_PORT = 8845;
/**
* 获取当前用户目录。
*/
function getHomeDirectory(): string {
return process.env.HOME || process.env.USERPROFILE || os.homedir() || ".";
}
/**
* 获取开发环境下的配置文件路径。
*/
function getConfigFilePath(): string {
if (process.platform === "linux") {
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
const baseDirectory =
xdgConfigHome && path.isAbsolute(xdgConfigHome)
? xdgConfigHome
: path.join(getHomeDirectory(), ".config");
return path.join(baseDirectory, APP_NAME, CONFIG_FILE_NAME);
}
if (process.env.APPDATA) {
return path.join(process.env.APPDATA, APP_NAME, CONFIG_FILE_NAME);
}
return path.join(getHomeDirectory(), `.${APP_NAME}`, CONFIG_FILE_NAME);
}
/**
* 将配置中的 server_ip 规范化为 Vite 代理 target。
*/
function buildProxyTarget(serverIp: string): string {
const raw = serverIp.trim();
if (!raw) {
return "";
}
if (raw.startsWith("http://") || raw.startsWith("https://")) {
return raw.replace(/\/$/, "");
}
const hostPort = raw.replace(/^\/+/, "");
const hasPort = /:\d+$/.test(hostPort) || /^\[.+\]:\d+$/.test(hostPort);
if (hasPort) {
return `http://${hostPort}`;
}
return `http://${hostPort}:${DEFAULT_API_PORT}`;
}
/**
* 从本地 config.json 读取开发代理目标地址。
*/
function resolveProxyTarget(): string {
const configFilePath = getConfigFilePath();
if (!fs.existsSync(configFilePath)) {
return "";
}
try {
const content = fs.readFileSync(configFilePath, "utf8");
const parsed = JSON.parse(content) as Record<string, unknown>;
const serverIp = typeof parsed.server_ip === "string" ? parsed.server_ip : "";
return buildProxyTarget(serverIp);
} catch {
return "";
}
}
const proxyTarget = resolveProxyTarget();
// https://vite.dev/config/
export default defineConfig(async () => ({
plugins: [
vue(),
AutoImport({
imports: ["vue", "vue-router"],
dts: false,
resolvers: [ElementPlusResolver()],
}),
Components({
dts: false,
resolvers: [ElementPlusResolver()],
}),
],
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (!id.includes("node_modules")) {
return undefined;
}
if (id.includes("element-plus") || id.includes("@element-plus")) {
return "vendor-element-plus";
}
if (id.includes("vue-router")) {
return "vendor-router";
}
if (id.includes("axios")) {
return "vendor-axios";
}
if (id.includes("node_modules/vue/") || id.includes("node_modules/@vue/")) {
return "vendor-vue";
}
return "vendor-misc";
},
},
},
},
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
//
// 1. prevent Vite from obscuring rust errors
clearScreen: false,
// 2. tauri expects a fixed port, fail if that port is not available
server: {
port: 1420,
strictPort: true,
host: host || false,
proxy: proxyTarget
? {
[API_QUEUE_CALLER_PATH]: {
target: proxyTarget,
changeOrigin: true,
},
}
: undefined,
hmr: host
? {
protocol: "ws",
host,
port: 1421,
}
: undefined,
watch: {
// 3. tell Vite to ignore watching `src-tauri`
ignored: ["**/src-tauri/**"],
},
},
}));