Files
open-gateway-front/vite.config.ts
T

182 lines
8.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ConfigEnv, UserConfig, defineConfig, type Plugin } from "vite";
import { createHtmlPlugin } from "vite-plugin-html";
import vue from "@vitejs/plugin-vue";
import path, { resolve } from "path";
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
import ViteAutoImport from "unplugin-auto-import/vite";
import UnoCSS from "@unocss/vite";
import presetUno from "@unocss/preset-uno";
import presetRemToPx from "@unocss/preset-rem-to-px";
// mock 数据层(仅 --mode mock 注册,见下方 gatewayAdminMockPlugin;零依赖手写中间件而非
// vite-plugin-mock:后者独立打包 mock 文件为第二模块实例,无法实现"整页刷新重置内存态")
import { handleGatewayMockRequest, resetGatewayMockState } from "./src/assets/mock/gatewayApi";
/** 内置 mock(仅 serve + --mode mock):拦截 /open-gateway/api/internal/** 按后端契约应答。
* 直接注册在 configureServer(先于 vite 内部中间件,含 /open-gateway/api 代理);
* 整页文档请求(刷新/直达)触发内存态重置回静态种子,SPA 站内切换不重置。 */
function gatewayAdminMockPlugin(): Plugin {
return {
name: "gateway-admin-mock",
apply: "serve",
configureServer(server) {
server.middlewares.use((req, _res, next) => {
const accept = String(req.headers.accept ?? "");
if (accept.includes("text/html")) resetGatewayMockState();
next();
});
server.middlewares.use(async (req, res, next) => {
try {
if (!(await handleGatewayMockRequest(req, res))) next();
} catch (e) {
next(e);
}
});
},
};
}
// 构建输出恒为 dist 根:CI 打包 zip 的根目录必须直接是 index.html(projman 前端发布校验 zip 根含 html)。
// 不再有 dist/base 中间层——outDir=dist/base 时 zip 打 dist 整层,zip 根只有 base/,发布会校验失败。
// dev(--mode dev)读 .env.dev,VITE_SERVICE_HOST 指向同源前缀 /open-gateway(经下方 proxy 打到 base 域)
export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
const outDir = "dist";
return {
plugins: [
// 仅 --mode mock 启用内置 mock;dev/联调/正式 build 行为零变化
...(mode === "mock" ? [gatewayAdminMockPlugin()] : []),
vue(),
createSvgIconsPlugin({
iconDirs: [resolve(process.cwd(), "src/assets/icons")],
symbolId: "icon-[dir]-[name]",
inject: "body-last",
customDomId: "__svg__icons__dom__",
}),
ViteAutoImport({
imports: [
"vue",
"vue-router",
{
"view-ui-plus": ["Button", "Table", "Modal", "Message", "Form", "FormItem", "Input", "Select"],
},
{
from: "alova/client",
imports: ["usePagination", "useRequest", "useWatcher", "useForm"],
},
],
dts: "./src/auto-imports.d.ts",
dirs: ["src/api"],
}),
createHtmlPlugin({
minify: true,
pages: [
{
entry: "src/main.ts",
template: "index.html",
filename: "index.html",
injectOptions: {
data: {
title: "开放网关",
injectScript: ``,
},
},
},
],
}),
UnoCSS({
presets: [
presetUno(),
presetRemToPx({ baseFontSize: 4 }), // 1单位=1px(去rem化)
],
shortcuts: {
"flex-center": "flex items-center justify-center",
btn: "px-16px py-8px rounded-4px cursor-pointer transition-all duration-200",
"btn-primary": "bg-blue-600 text-white hover:bg-blue-700",
card: "bg-white rounded-8px shadow-md p-16px",
"text-ellipsis": "truncate",
"text-multi-ellipsis": "line-clamp-2",
},
theme: {
fontSize: {
xs: "12px",
sm: "14px",
base: "16px",
lg: "18px",
xl: "20px",
"2xl": "24px",
},
},
}),
],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
server: {
host: "localhost",
port: 8131,
// 本地联调:/open-gateway/api/* → base 域(Caddy 剥前缀后转发到网关容器网内 10013)
// 走代理而非跨源直连:网关无 CORS,且 10013 仅绑容器网内 127.0.0.1
// 设 YH_GW_PROXY_TARGET(如 http://localhost:10013)= 不经 base 域直打本地网关,
// 此时剥掉 /open-gateway 前缀(原本由 Caddy 剥);不设则行为与线上联调零变化
proxy: {
"/open-gateway/api": {
target: process.env.YH_GW_PROXY_TARGET || "http://base.yunhaixingtong.com",
changeOrigin: true,
...(process.env.YH_GW_PROXY_TARGET
? { rewrite: (p: string) => p.replace(/^\/open-gateway/, "") }
: {}),
},
// 主题通道本地联调(照 Notice 配方):index.html loader 走同源相对 /static/js/yh-theme-init.js,
// manifest/CSS 经此代理到中央通道;base 域不可达(无 VPN)时由 npm run dev:mock
// (scripts/start-mock.mjs)以 YH_THEME_PROXY_TARGET 把目标覆盖为本地 9527 静态服务。
"/static": {
target: process.env.YH_THEME_PROXY_TARGET || "http://base.yunhaixingtong.com",
changeOrigin: true,
},
// 超管门槛探测(/userbase/base/User/CurrentUser,见 src/utils/superGate.ts):
// 生产页面与 userbase 同挂 base 域、同源相对路径直连;本地 dev 经此代理兜到
// base 域(无平台 Cookie 时探测失败按放行处理,可用 VITE_SUPER_GATE=off 旁路),
// dev:mock 由内置 mock 中间件先于代理应答(YH_MOCK_SUPER=0 演示非超管态)。
"/userbase": {
target: process.env.YH_UB_PROXY_TARGET || "http://base.yunhaixingtong.com",
changeOrigin: true,
},
},
},
base: "./",
build: {
target: "modules",
outDir,
assetsDir: "assets",
sourcemap: false,
minify: "esbuild",
chunkSizeWarningLimit: 1000,
cssTarget: "chrome61",
rollupOptions: {
input: {
main: resolve("index.html"),
},
output: {
chunkFileNames: "static/js/[name]-[hash].js",
entryFileNames: "static/js/[name]-[hash].js",
assetFileNames: (assetInfo: any) => {
if (assetInfo.type === "asset" && /\.(jpe?g|png|gif|svg)$/i.test(assetInfo.name)) {
return "static/img/[name].[hash][ext]";
}
if (assetInfo.type === "asset" && /\.(ttf|woff|woff2|eot)$/i.test(assetInfo.name)) {
return "static/fonts/[name].[hash][ext]";
}
return "static/[ext]/[name]-[hash].[ext]";
},
},
manualEntrypoint: "index.html",
},
},
};
});