import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import fs from 'fs' import path from 'path' const ortDistDir = path.resolve(__dirname, 'node_modules/onnxruntime-web/dist') const vadDistDir = path.resolve(__dirname, 'node_modules/@ricky0123/vad-web/dist') const publicDir = path.resolve(__dirname, 'public') // 需要复制到 public 的 VAD 模型/工作线程 const vadFiles = [ { src: vadDistDir, name: 'silero_vad_legacy.onnx' }, { src: vadDistDir, name: 'silero_vad_v5.onnx' }, { src: vadDistDir, name: 'vad.worklet.bundle.min.js' }, ] // 需要复制到 public 的 ONNX Runtime WASM 文件(生产环境需要) const ortFiles = [ { src: ortDistDir, name: 'ort-wasm-simd-threaded.mjs' }, { src: ortDistDir, name: 'ort-wasm-simd-threaded.wasm' }, { src: ortDistDir, name: 'ort-wasm-simd.mjs' }, { src: ortDistDir, name: 'ort-wasm-simd.wasm' }, { src: ortDistDir, name: 'ort-wasm.mjs' }, { src: ortDistDir, name: 'ort-wasm.wasm' }, ] /** 把所需文件复制到 public 目录(不存在则复制) */ function copyAssetsToPublic() { for (const { src, name } of [...vadFiles, ...ortFiles]) { const srcFile = path.join(src, name) const destFile = path.join(publicDir, name) if (fs.existsSync(srcFile) && !fs.existsSync(destFile)) { fs.copyFileSync(srcFile, destFile) } } } export default defineConfig({ server: { proxy: { '/ws': { target: 'http://localhost:8080', ws: true, }, '/api': { target: 'http://localhost:8080', }, }, }, plugins: [ react(), { name: 'serve-vad-assets', // 1. 启动时将 VAD 模型 + ORT WASM 复制到 public configResolved() { copyAssetsToPublic() }, // 2. 开发模式中间件:拦截 WASM 相关请求,确保 MIME 类型正确 configureServer(server) { server.middlewares.use((req, res, next) => { const url = req.url?.split('?')[0] ?? '' const wasmMatch = url.match(/\/(ort-wasm[\w-]*\.(mjs|wasm))$/) if (wasmMatch) { const fileName = wasmMatch[1] const filePath = path.join(ortDistDir, fileName) if (fs.existsSync(filePath)) { res.setHeader('Content-Type', fileName.endsWith('.wasm') ? 'application/wasm' : 'application/javascript') res.setHeader('Cache-Control', 'no-cache') res.end(fs.readFileSync(filePath)) return } } next() }) }, // 3. 构建阶段确保所有资源都在 dist 中 writeBundle() { const distDir = path.resolve(__dirname, 'dist') for (const { src, name } of [...vadFiles, ...ortFiles]) { const srcFile = path.join(src, name) const destFile = path.join(distDir, name) if (fs.existsSync(srcFile) && !fs.existsSync(destFile)) { fs.copyFileSync(srcFile, destFile) } } }, }, ], })