import fs from "node:fs"; import path from "node:path"; import { reactRouter } from "@react-router/dev/vite"; import tailwindcss from "@tailwindcss/vite"; import { defineConfig, loadEnv, type Plugin } from "vite"; /** 读取 git 短哈希(不依赖 git 命令) */ function readGitShortSha(cwd: string): string | null { try { const gitDir = path.join(cwd, ".git"); const head = fs.readFileSync(path.join(gitDir, "HEAD"), "utf8").trim(); let sha = head; if (head.startsWith("ref: ")) { const ref = head.slice(5); const refFile = path.join(gitDir, ref); if (fs.existsSync(refFile)) { sha = fs.readFileSync(refFile, "utf8").trim(); } else { const packed = fs.readFileSync(path.join(gitDir, "packed-refs"), "utf8"); const line = packed.split("\n").find((l) => l.endsWith(` ${ref}`)); if (!line) return null; sha = line.split(" ")[0] ?? ""; } } return /^[0-9a-f]{40}$/.test(sha) ? sha.slice(0, 7) : null; } catch { return null; } } /** 构建时注入 __APP_VERSION__ 并输出 version.json;优先 APP_VERSION,其次 git 短哈希,最后时间戳 */ function appVersion(): Plugin { const repoRoot = path.resolve(process.cwd(), "../.."); const version = process.env.APP_VERSION?.trim() || readGitShortSha(repoRoot) || `build-${Date.now().toString(36)}`; return { name: "app-version", config() { return { define: { __APP_VERSION__: JSON.stringify(version) } }; }, generateBundle() { this.emitFile({ type: "asset", fileName: "version.json", source: JSON.stringify({ version, builtAt: new Date().toISOString() }), }); }, }; } export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), ""); const apiTarget = env.VITE_API_TARGET || "http://localhost:4390"; return { plugins: [tailwindcss(), reactRouter(), appVersion()], resolve: { tsconfigPaths: true }, server: { port: 5180, strictPort: true, // 依赖装在仓库根 node_modules/.deno(deno workspace),vite 找不到 npm workspace 根,需显式放行 fs: { allow: [path.resolve(process.cwd(), "../..")] }, proxy: { "/api": { target: apiTarget, changeOrigin: true }, }, }, }; });