import { copyFileSync, mkdirSync } from 'node:fs' import { resolve } from 'node:path' import { defineConfig, externalizeDepsPlugin } from 'electron-vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' import type { Plugin } from 'vite' /** 构建期把主题 token 样式表拷到 out/renderer/tokens.css: * 生产环境 src/ 不进包,插件页经 peer://assets/tokens.css 引用它保证深浅色/accent 连续 */ function copyTokensCss(): Plugin { return { name: 'aso-copy-tokens-css', closeBundle() { const src = resolve(__dirname, 'src/renderer/src/styles/beautifului.css') const outDir = resolve(__dirname, 'out/renderer') try { mkdirSync(outDir, { recursive: true }) copyFileSync(src, resolve(outDir, 'tokens.css')) } catch (err) { this.warn(`tokens.css 拷贝失败: ${err instanceof Error ? err.message : String(err)}`) } } } } export default defineConfig({ main: { // pi SDK 为纯 ESM 包,主进程输出 ESM(Electron ≥28 支持) plugins: [externalizeDepsPlugin()], build: { rollupOptions: { // electron 保持内置模块导入;pi 全家桶运行时从 node_modules 以 ESM 加载, // 同时避开 pi 实验性导出引用的未声明子包问题 external: ['electron', /^@earendil-works\//], output: { format: 'es', entryFileNames: '[name].mjs' } } }, resolve: { alias: { '@main': resolve(__dirname, 'src/main'), '@shared': resolve(__dirname, 'src/shared') } } }, preload: { plugins: [externalizeDepsPlugin()], build: { rollupOptions: { // electron 解析为内置模块,避免把 npm 包打进 preload external: ['electron'], output: { format: 'cjs', // "type":"module" 下 .js 会被当 ESM 加载,preload 必须用 .cjs entryFileNames: '[name].cjs' } } }, resolve: { alias: { '@shared': resolve(__dirname, 'src/shared') } } }, renderer: { // Windows 上 Hyper-V/WSL 的 WinNAT 每次开机会随机保留若干端口段, // 默认 5173 常被圈进保留段导致 EACCES;固定用 5323 避开(若日后再撞, // 可换端口,或管理员执行 net stop winnat && net start winnat 后 // netsh int ipv4 add excludedportrange protocol=tcp startport=<端口> numberofports=1 永久占用) server: { port: 5323, // 允许 dev server 读取工作区源码包(@aso/plugin-sdk 从 packages/ 链接进来) fs: { allow: [resolve(__dirname, '../..')] } }, optimizeDeps: { // sdk 是源码形态(exports 指向 .ts/.tsx),必须走源码 transform 而非预打包 exclude: ['@aso/plugin-sdk'] }, plugins: [react(), tailwindcss(), copyTokensCss()], resolve: { alias: { '@': resolve(__dirname, 'src/renderer/src'), '@renderer': resolve(__dirname, 'src/renderer/src'), '@shared': resolve(__dirname, 'src/shared') } } } })