Skip to content
Clone
b868469
107 lines 3.6 KB
import { existsSync, renameSync, rmSync } from 'node:fs'
import { join } from 'node:path'
import { fileURLToPath } from 'node:url'
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'
import { type Connect, defineConfig, loadEnv, type Plugin } from 'vite'
/// 应用前缀 → 入口 HTML,与 lib/service/webapi/src/assets.rs 的 APP_ENTRIES 保持一致。
const APP_ENTRIES: Record<string, string> = {
auth: '/auth/index.html',
app: '/app/index.html',
}
/// dev / preview 下按后端 assets::serve 的规则把子应用路由回落到各自入口。
function mpaFallback(): Plugin {
const rewrite = (request: { url?: string }, landing?: string) => {
const path = (request.url || '').split('?')[0]
if (!path || path === '/') {
if (landing) request.url = landing
return
}
if (path.includes('.')) return
const first = path.split('/')[1] || ''
const entry = APP_ENTRIES[first]
if (entry) request.url = entry
}
const middleware =
(landing?: string): Connect.NextHandleFunction =>
(request, _response, next) => {
rewrite(request, landing)
next()
}
return {
name: 'mpa-fallback',
configureServer(server) {
// dev 直接读源码目录,落地页入口在 view/index/index.html。
server.middlewares.use(middleware('/index/index.html'))
},
configurePreviewServer(server) {
// preview 读 dist,落地页产物已归位到 index.html,无需改写。
server.middlewares.use(middleware())
},
}
}
/// Vite 按 HTML 相对 root 的路径生成产物;落地页入口在 view/index/ 下,这里归位到 dist/index.html。
function landingOutput(outDir: string): Plugin {
return {
name: 'landing-output',
apply: 'build',
closeBundle() {
const source = join(outDir, 'index', 'index.html')
if (!existsSync(source)) return
renameSync(source, join(outDir, 'index.html'))
rmSync(join(outDir, 'index'), { recursive: true, force: true })
},
}
}
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
root: 'view',
publicDir: 'public',
build: {
outDir: 'dist',
emptyOutDir: true,
rollupOptions: {
input: {
landing: fileURLToPath(new URL('./view/index/index.html', import.meta.url)),
auth: fileURLToPath(new URL('./view/auth/index.html', import.meta.url)),
app: fileURLToPath(new URL('./view/app/index.html', import.meta.url)),
},
},
},
plugins: [
react(),
tailwindcss(),
mpaFallback(),
landingOutput(fileURLToPath(new URL('./view/dist', import.meta.url))),
],
resolve: {
alias: {
'@kenapi/apiclient': fileURLToPath(new URL('./packages/apiclient', import.meta.url)),
'@': fileURLToPath(new URL('./view/auth/src', import.meta.url)),
'@app': fileURLToPath(new URL('./view/app/src', import.meta.url)),
'@livekit/components-core': fileURLToPath(new URL('./view/app/src/vendor/livekit/core/index.ts', import.meta.url)),
'@livekit/components-styles': fileURLToPath(new URL('./view/app/src/vendor/livekit/styles', import.meta.url)),
},
},
optimizeDeps: { include: ['@noble/hashes/sha2.js'] },
server: {
port: 15474,
proxy: {
'^/api/v1(?:/|$)|^/.well-known/|^/pages(?:/|$)': {
target: env.AUTH_API_PROXY || 'http://127.0.0.1:7051',
changeOrigin: true,
},
'^/socket.io(?:/|$)': {
target: env.EVENT_PROXY || 'http://127.0.0.1:7031',
changeOrigin: true,
ws: true,
},
},
},
}
})