Files
hermes-ui/vite.config.ts
toor 836d0228d2 Phase 007: migrate every remaining view from naive-ui to Arco Design Vue
The project now has exactly one UI library. Every naive-ui component in
packages/client/src is replaced by its Arco equivalent across 24 views and
roughly 80 components, and naive-ui is dropped from package.json along with
its transitive vueuc / @css-render / vdirs / seemly dependencies.

The migration is rendering-layer only. No store logic, no API contract, and
no /chat-run payload was touched.

Three classes of leftover were invisible to `grep naive-ui` and are now
covered by tests/client/no-naive-ui.test.ts, which asserts all three:
  - dead .n-* class names in style blocks
  - dead --n-* custom properties
  - naive-ui in package.json

Notable behavioural traps handled along the way, recorded in
docs/arco-migration-rules.md:
  - a-input-password defaults to masked; passing default-visibility="false"
    would have exposed API keys in clear text
  - a-upload fires a real XHR unless auto-upload is false
  - nested Trigger components fight over the first element child, so the
    group-chat settings dropdown was flattened
  - Arco renders tooltip default-slot text inline, which was silently
    collapsing the chat and group-chat toolbars
2026-10-18 22:57:25 +08:00

116 lines
3.3 KiB
TypeScript
Raw Permalink 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 } from 'vite'
import vue from '@vitejs/plugin-vue'
import type { ProxyOptions } from 'vite'
import { resolve } from 'path'
import pkg from './package.json'
const FRONTEND_PORT = Number(process.env.HERMES_WEB_UI_FRONTEND_PORT || 8649)
const BACKEND_PORT = process.env.HERMES_WEB_UI_BACKEND_PORT || '8648'
const BACKEND = `http://127.0.0.1:${BACKEND_PORT}`
function createProxyConfig(): ProxyOptions {
return {
target: BACKEND,
changeOrigin: true,
ws: true,
configure: (proxy) => {
proxy.on('proxyReq', (proxyReq) => {
proxyReq.removeHeader('origin')
proxyReq.removeHeader('referer')
})
proxy.on('proxyReqWs', (proxyReq) => {
proxyReq.removeHeader('origin')
proxyReq.removeHeader('referer')
})
proxy.on('proxyRes', (proxyRes) => {
proxyRes.headers['cache-control'] = 'no-cache'
proxyRes.headers['x-accel-buffering'] = 'no'
})
},
}
}
export default defineConfig({
root: 'packages/client',
plugins: [vue()],
define: {
__APP_VERSION__: JSON.stringify(pkg.version),
},
resolve: {
alias: {
'@': resolve(__dirname, 'packages/client/src'),
},
},
build: {
outDir: '../../dist/client',
emptyOutDir: true,
// Use esbuild for minification (much faster than terser)
minify: 'esbuild',
// Disable sourcemap generation for faster builds
sourcemap: false,
target: 'es2020',
// Increase chunk size warning limit (default: 500KB)
chunkSizeWarningLimit: 1000,
// CSS code splitting for better caching
cssCodeSplit: true,
rollupOptions: {
output: {
// Manual chunk splitting to speed up rendering
manualChunks(id) {
// Separate large heavy packages to avoid blocking other chunks
if (id.includes('node_modules/monaco-editor')) {
return 'monaco-editor'
}
if (id.includes('node_modules/mermaid')) {
return 'mermaid'
}
if (id.includes('node_modules/@xterm')) {
return 'xterm'
}
if (id.includes('node_modules')) {
// Arco 必须排在 vue 之前:它的 scope 名是 @arco-design/web-vue,
// 含 "vue" 子串,放在后面会被 vue-vendor 先吃掉。
if (id.includes('@arco-design')) {
return 'ui-vendor'
}
if (id.includes('vue') || id.includes('pinia') || id.includes('vue-router')) {
return 'vue-vendor'
}
return 'vendor'
}
},
// Optimize chunk file names for better caching
chunkFileNames: 'assets/js/[name]-[hash].js',
entryFileNames: 'assets/js/[name]-[hash].js',
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
},
},
},
optimizeDeps: {
// Pre-bundle all large dependencies for faster builds
include: [
'monaco-editor',
'mermaid',
'vue',
'vue-router',
'pinia',
'@arco-design/web-vue',
],
},
server: {
port: FRONTEND_PORT,
strictPort: true,
proxy: {
'/api': createProxyConfig(),
'/v1': createProxyConfig(),
'/health': createProxyConfig(),
'/upload': createProxyConfig(),
'/webhook': createProxyConfig(),
'/socket.io': {
target: BACKEND,
ws: true,
},
},
},
})