Files
udmin/frontend/vite.config.ts
ayou dd7857940f feat(flow): 新增流式执行模式与SSE支持
新增流式执行模式,通过SSE实时推送节点执行事件与日志
重构HTTP执行器与中间件,提取通用HTTP客户端组件
优化前端测试面板,支持流式模式切换与实时日志展示
更新依赖版本并修复密码哈希的随机数生成器问题
修复前端节点类型映射问题,确保Code节点表单可用
2025-09-21 01:48:24 +08:00

81 lines
3.5 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 { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'
// 单一配置文件 + 多环境 .env
// - .env.development / .env.production / .env.staging 中配置变量
// - 通过 loadEnv 读取并应用到开发服务器与代理
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, '.', '')
const port = Number(env.VITE_PORT || 5173)
const open = String(env.VITE_OPEN ?? 'true').toLowerCase() === 'true' || env.VITE_OPEN === '1'
const proxyTarget = env.VITE_ADMIN_PROXY_PATH || 'http://127.0.0.1:9898'
return {
plugins: [
react({
babel: {
plugins: [
['@babel/plugin-proposal-decorators', { legacy: true }],
['babel-plugin-transform-typescript-metadata'],
['@babel/plugin-proposal-class-properties', { loose: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
['@babel/plugin-proposal-private-property-in-object', { loose: true }]
]
}
})
],
server: {
port,
open,
proxy: {
'/api': {
target: proxyTarget,
changeOrigin: true,
// 为 SSE 透传加固:禁用超时并保持连接
proxyTimeout: 0,
timeout: 0,
headers: { 'Connection': 'keep-alive' },
// 关键:在 dev 代理层面禁止缓冲/缓存,强制以 chunk 方式向浏览器侧回传,避免一次性聚合
configure: (proxy: any) => {
// 移除 Accept-Encoding避免后端压缩导致中间件缓冲
proxy.on('proxyReq', (proxyReq: any, req: any) => {
const url: string = req?.url || ''
if (url.includes('/run/stream')) {
try {
if (typeof proxyReq.removeHeader === 'function') proxyReq.removeHeader('accept-encoding')
proxyReq.setHeader('accept', 'text/event-stream')
proxyReq.setHeader('connection', 'keep-alive')
} catch {}
}
})
proxy.on('proxyRes', (proxyRes: any, req: any, res: any) => {
const url: string = req?.url || ''
const ct: string = String(proxyRes.headers?.['content-type'] || '')
const isSse = url.includes('/run/stream') || ct.includes('text/event-stream')
if (!isSse) return
try {
// 直接改写后端返回头,确保为 SSE 且无长度/压缩
proxyRes.headers['content-type'] = 'text/event-stream; charset=utf-8'
proxyRes.headers['cache-control'] = 'no-cache'
proxyRes.headers['pragma'] = 'no-cache'
proxyRes.headers['x-accel-buffering'] = 'no'
delete proxyRes.headers['content-length']
delete proxyRes.headers['content-encoding']
// 同步确保 devServer 给浏览器的头一致,并尽早发送
res.setHeader('Content-Type', 'text/event-stream; charset=utf-8')
res.setHeader('Cache-Control', 'no-cache')
res.setHeader('Pragma', 'no-cache')
res.setHeader('X-Accel-Buffering', 'no')
if (typeof res.removeHeader === 'function') res.removeHeader('Content-Length')
if (typeof res.removeHeader === 'function') res.removeHeader('Content-Encoding')
if (typeof res.flushHeaders === 'function') res.flushHeaders()
} catch {}
})
}
}
}
}
}
})