| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- import { defineConfig } from 'vite';
- import vue from '@vitejs/plugin-vue';
- import electron from 'vite-plugin-electron';
- import renderer from 'vite-plugin-electron-renderer';
- import AutoImport from 'unplugin-auto-import/vite';
- import Components from 'unplugin-vue-components/vite';
- import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
- import { resolve } from 'path';
- import { existsSync, readFileSync } from 'fs';
- function readServerEnv() {
- const envPath = resolve(__dirname, '../server/.env');
- const env: Record<string, string> = {};
- if (!existsSync(envPath)) return env;
- const lines = readFileSync(envPath, 'utf8').split(/\r?\n/);
- for (const line of lines) {
- const trimmed = line.trim();
- if (!trimmed || trimmed.startsWith('#')) continue;
- const index = trimmed.indexOf('=');
- if (index <= 0) continue;
- const key = trimmed.slice(0, index).trim();
- const value = trimmed.slice(index + 1).trim().replace(/^['"]|['"]$/g, '');
- env[key] = value;
- }
- return env;
- }
- function getDevApiTarget() {
- const serverEnv = readServerEnv();
- const rawHost = process.env.VITE_DEV_API_HOST || serverEnv.HOST || '127.0.0.1';
- const host = rawHost === '0.0.0.0' || rawHost === '::' ? '127.0.0.1' : rawHost;
- const port = process.env.VITE_DEV_API_PORT || serverEnv.PORT || '3000';
- return `http://${host}:${port}`;
- }
- export default defineConfig(({ command }) => {
- const isServe = command === 'serve';
- const isBuild = command === 'build';
- const devApiTarget = getDevApiTarget();
- return {
- // Electron 打包后从 file:// 加载,需使用相对路径
- base: isBuild ? './' : '/',
- resolve: {
- alias: {
- '@': resolve(__dirname, 'src'),
- },
- },
- plugins: [
- vue({
- template: {
- compilerOptions: {
- // 将 webview 标记为自定义元素(Electron 特有标签)
- isCustomElement: (tag) => tag === 'webview',
- },
- },
- }),
- AutoImport({
- imports: ['vue', 'vue-router', 'pinia'],
- resolvers: [ElementPlusResolver()],
- dts: 'src/auto-imports.d.ts',
- }),
- Components({
- resolvers: [
- ElementPlusResolver(),
- // 自动解析 Element Plus 图标组件
- {
- type: 'component',
- resolve: (name: string) => {
- // Element Plus 图标组件通常是 PascalCase 且不以 El 开头
- const iconNames = [
- 'Fold', 'Expand', 'Loading', 'DocumentCopy', 'Message', 'Close',
- 'Refresh', 'Delete', 'Right', 'FolderDelete', 'DataAnalysis',
- 'User', 'Film', 'Upload', 'Clock', 'Setting', 'Document',
- 'Monitor', 'TrendCharts', 'ChatDotRound', 'ArrowDown', 'ArrowLeft',
- 'ArrowRight', 'VideoPlay', 'CircleCheck', 'CircleClose', 'Lock',
- 'Picture', 'Plus', 'Search', 'Edit', 'Download', 'MoreFilled',
- 'MagicStick',
- ];
- if (iconNames.includes(name)) {
- return { name, from: '@element-plus/icons-vue' };
- }
- },
- },
- ],
- dts: 'src/components.d.ts',
- }),
- electron([
- {
- entry: 'electron/main.ts',
- onstart(options) {
- if (process.env.VSCODE_DEBUG) {
- console.log('[startup] Electron App');
- } else {
- options.startup();
- }
- },
- vite: {
- build: {
- sourcemap: isServe,
- minify: isBuild,
- outDir: 'dist-electron',
- rollupOptions: {
- external: ['electron'],
- output: {
- format: 'cjs',
- },
- },
- },
- },
- },
- {
- entry: 'electron/preload.ts',
- onstart(options) {
- options.reload();
- },
- vite: {
- build: {
- sourcemap: isServe ? 'inline' : undefined,
- minify: isBuild,
- outDir: 'dist-electron',
- rollupOptions: {
- external: ['electron'],
- output: {
- format: 'cjs',
- },
- },
- },
- },
- },
- ]),
- renderer(),
- ],
- css: {
- preprocessorOptions: {
- scss: {
- additionalData: `@use "@/styles/variables.scss" as *;`,
- },
- },
- },
- server: {
- host: '127.0.0.1',
- port: 15173,
- strictPort: true,
- proxy: {
- '/api': {
- target: devApiTarget,
- changeOrigin: true,
- },
- '/ws': {
- target: devApiTarget.replace(/^http/, 'ws'),
- ws: true,
- },
- },
- },
- build: {
- outDir: 'dist',
- emptyOutDir: true,
- rollupOptions: {
- output: {
- // manualChunks 在 Electron file:// 协议下会导致跨 chunk 的 ES module
- // 静态 import 失败,引发白屏。如需分包优化,改用自定义协议加载。
- },
- },
- },
- };
- });
|