将 'silk-wasm' 加入主进程 vite external 列表。
silk-wasm 默认会被 rollup 内联进 main.js,CI 构建环境下其内部
import_meta_url 变量被错误优化为 {}.url(即 undefined),
触发 createRequire(undefined) 报错,SILK 解码失败,
语音转写功能完全不可用。
silk-wasm 本身已在 package.json 的 asarUnpack 中(line 184-185),
强制 external 后正常走 require() 从 unpacked 加载,与原意图对齐。
本地 macOS Apple Silicon 验证:
- 构建产物 main.js 已 0 内联(grep tencent silk = 0)
- require("silk-wasm") 动态保留
- 实测语音转写恢复正常
254 lines
7.5 KiB
TypeScript
254 lines
7.5 KiB
TypeScript
import { defineConfig } from 'vite'
|
|
import react from '@vitejs/plugin-react'
|
|
import electron from 'vite-plugin-electron'
|
|
import renderer from 'vite-plugin-electron-renderer'
|
|
import { resolve } from 'path'
|
|
|
|
const handleElectronOnStart = (options: { reload: () => void }) => {
|
|
options.reload()
|
|
}
|
|
|
|
const exportWorkerElectronShimPlugin = () => {
|
|
const virtualId = 'virtual:weflow-export-worker-electron'
|
|
const resolvedVirtualId = `\0${virtualId}`
|
|
|
|
return {
|
|
name: 'weflow-export-worker-electron-shim',
|
|
enforce: 'pre' as const,
|
|
resolveId(id: string) {
|
|
if (id === virtualId) return resolvedVirtualId
|
|
return null
|
|
},
|
|
load(id: string) {
|
|
if (id !== resolvedVirtualId) return null
|
|
return `
|
|
import { homedir, tmpdir } from 'os'
|
|
import { join } from 'path'
|
|
|
|
const workerUserDataPath = () => String(process.env.WEFLOW_USER_DATA_PATH || process.env.WEFLOW_CONFIG_CWD || '').trim()
|
|
const appDataPath = () => {
|
|
if (process.platform === 'win32' && process.env.APPDATA) return process.env.APPDATA
|
|
if (process.platform === 'darwin') return join(homedir(), 'Library', 'Application Support')
|
|
return process.env.XDG_CONFIG_HOME || join(homedir(), '.config')
|
|
}
|
|
const getPath = (name) => {
|
|
if (name === 'userData') return workerUserDataPath() || join(appDataPath(), 'WeFlow')
|
|
if (name === 'documents') return join(homedir(), 'Documents')
|
|
if (name === 'desktop') return join(homedir(), 'Desktop')
|
|
if (name === 'downloads') return join(homedir(), 'Downloads')
|
|
if (name === 'temp') return tmpdir()
|
|
if (name === 'appData') return appDataPath()
|
|
return process.cwd()
|
|
}
|
|
|
|
export const app = {
|
|
isPackaged: Boolean(process.resourcesPath && process.env.NODE_ENV !== 'development'),
|
|
getPath,
|
|
getAppPath: () => process.cwd(),
|
|
getName: () => 'WeFlow',
|
|
getVersion: () => process.env.npm_package_version || '0.0.0'
|
|
}
|
|
export const BrowserWindow = { getAllWindows: () => [] }
|
|
export const dialog = { showMessageBox: async () => ({ response: 0, checkboxChecked: false }) }
|
|
export const shell = { openExternal: async () => false, showItemInFolder: () => {} }
|
|
export const ipcMain = { on: () => {}, handle: () => {}, removeHandler: () => {} }
|
|
export const ipcRenderer = { sendSync: () => ({}) }
|
|
export const safeStorage = {
|
|
isEncryptionAvailable: () => false,
|
|
encryptString: (value) => Buffer.from(String(value || ''), 'utf8'),
|
|
decryptString: (value) => Buffer.isBuffer(value) ? value.toString('utf8') : Buffer.from(value).toString('utf8')
|
|
}
|
|
export const Notification = class {
|
|
static isSupported() { return false }
|
|
on() { return this }
|
|
show() {}
|
|
close() {}
|
|
}
|
|
export default { app, BrowserWindow, dialog, shell, ipcMain, ipcRenderer, safeStorage, Notification }
|
|
`
|
|
},
|
|
transform(code: string, id: string) {
|
|
if (!/\.[cm]?[jt]s$/.test(id)) return null
|
|
if (!code.includes("'electron'") && !code.includes('"electron"')) return null
|
|
const next = code
|
|
.replace(/from\s+(['"])electron\1/g, `from '${virtualId}'`)
|
|
.replace(/import\s*\(\s*(['"])electron\1\s*\)/g, `import('${virtualId}')`)
|
|
.replace(/require\s*\(\s*(['"])electron\1\s*\)/g, `require('${virtualId}')`)
|
|
return next === code ? null : { code: next, map: null }
|
|
}
|
|
}
|
|
}
|
|
|
|
export default defineConfig({
|
|
base: './',
|
|
server: {
|
|
port: 3000,
|
|
strictPort: false // 如果3000被占用,自动尝试下一个
|
|
},
|
|
build: {
|
|
chunkSizeWarningLimit: 900,
|
|
commonjsOptions: {
|
|
ignoreDynamicRequires: true
|
|
}
|
|
},
|
|
optimizeDeps: {
|
|
exclude: []
|
|
},
|
|
plugins: [
|
|
react(),
|
|
electron([
|
|
{
|
|
entry: 'electron/main.ts',
|
|
onstart: handleElectronOnStart,
|
|
vite: {
|
|
build: {
|
|
outDir: 'dist-electron',
|
|
rollupOptions: {
|
|
external: [
|
|
'better-sqlite3',
|
|
'koffi',
|
|
'fsevents',
|
|
'whisper-node',
|
|
'shelljs',
|
|
'exceljs',
|
|
'node-llama-cpp',
|
|
'@vscode/sudo-prompt',
|
|
'silk-wasm'
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
entry: 'electron/annualReportWorker.ts',
|
|
onstart: handleElectronOnStart,
|
|
vite: {
|
|
build: {
|
|
outDir: 'dist-electron',
|
|
rollupOptions: {
|
|
external: [
|
|
'koffi',
|
|
'fsevents'
|
|
],
|
|
output: {
|
|
entryFileNames: 'annualReportWorker.js',
|
|
inlineDynamicImports: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
entry: 'electron/dualReportWorker.ts',
|
|
onstart: handleElectronOnStart,
|
|
vite: {
|
|
build: {
|
|
outDir: 'dist-electron',
|
|
rollupOptions: {
|
|
external: [
|
|
'koffi',
|
|
'fsevents'
|
|
],
|
|
output: {
|
|
entryFileNames: 'dualReportWorker.js',
|
|
inlineDynamicImports: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
entry: 'electron/imageSearchWorker.ts',
|
|
onstart: handleElectronOnStart,
|
|
vite: {
|
|
build: {
|
|
outDir: 'dist-electron',
|
|
rollupOptions: {
|
|
output: {
|
|
entryFileNames: 'imageSearchWorker.js',
|
|
inlineDynamicImports: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
entry: 'electron/wcdbWorker.ts',
|
|
onstart: handleElectronOnStart,
|
|
vite: {
|
|
build: {
|
|
outDir: 'dist-electron',
|
|
rollupOptions: {
|
|
external: [
|
|
'better-sqlite3',
|
|
'koffi',
|
|
'fsevents'
|
|
],
|
|
output: {
|
|
entryFileNames: 'wcdbWorker.js',
|
|
inlineDynamicImports: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
entry: 'electron/transcribeWorker.ts',
|
|
onstart: handleElectronOnStart,
|
|
vite: {
|
|
build: {
|
|
outDir: 'dist-electron',
|
|
rollupOptions: {
|
|
external: [
|
|
'sherpa-onnx-node'
|
|
],
|
|
output: {
|
|
entryFileNames: 'transcribeWorker.js',
|
|
inlineDynamicImports: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
entry: 'electron/exportWorker.ts',
|
|
onstart: handleElectronOnStart,
|
|
vite: {
|
|
plugins: [exportWorkerElectronShimPlugin()],
|
|
build: {
|
|
outDir: 'dist-electron',
|
|
rollupOptions: {
|
|
external: [
|
|
'better-sqlite3',
|
|
'koffi',
|
|
'fsevents',
|
|
'exceljs'
|
|
],
|
|
output: {
|
|
entryFileNames: 'exportWorker.js',
|
|
inlineDynamicImports: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
entry: 'electron/preload.ts',
|
|
onstart: handleElectronOnStart,
|
|
vite: {
|
|
build: {
|
|
outDir: 'dist-electron'
|
|
}
|
|
}
|
|
}
|
|
]),
|
|
renderer()
|
|
],
|
|
resolve: {
|
|
dedupe: ['react', 'react-dom'],
|
|
alias: {
|
|
'@': resolve(__dirname, 'src')
|
|
}
|
|
}
|
|
})
|