buildadmin + electron 桌面应用开发

步骤 1:安装必要依赖
在 /web 目录内,执行如下命令:

language 复制代码
npm install electron vite-plugin-electron electron-builder -D
# 或
yarn add electron vite-plugin-electron electron-builder -D
# 或
pnpm install electron vite-plugin-electron electron-builder -D

步骤 2:创建 Electron 主进程文件
新建 electron/main.ts 文件:

language 复制代码
// 导入 Electron 的 app 和 BrowserWindow 模块
import { app, BrowserWindow, session } from 'electron'

// 创建浏览器窗口的函数
const createWindow = () => {
    // 创建一个新的浏览器窗口
    const win = new BrowserWindow({
        width: 1200, // 窗口宽度
        height: 800, // 窗口高度
        webPreferences: {
            // 网页功能设置
            nodeIntegration: true, // 启用Node.js集成(允许在渲染进程中使用Node.js API)
            contextIsolation: false, // 关闭上下文隔离(与nodeIntegration配合使用)
            webSecurity: false, // 禁用web安全策略(允许跨域请求)
            preload: 'preload.js', // 预加载脚本(在网页内容加载前运行)
        },
    })

    // 删除窗口的菜单栏
    win.removeMenu()

    // 判断当前环境是开发还是生产
    if (process.env.VITE_DEV_SERVER_URL) {
        // 开发模式:加载Vite开发服务器提供的URL
        win.loadURL(process.env.VITE_DEV_SERVER_URL)
        // 打开开发者工具(调试窗口)
        win.webContents.openDevTools()
    } else {
        // 生产模式:加载本地打包的HTML文件
        win.loadFile('index.html')
    }
}

// 当Electron完成初始化后执行
app.whenReady().then(() => {
    // 获取应用程序的主会话对象
    const mainSession = session.defaultSession

    // 注册一个网络请求拦截器,在请求发出前进行处理
    mainSession.webRequest.onBeforeRequest(
        // 配置选项:拦截所有URL(空数组表示匹配所有URL)
        { urls: [] },
        (details, callback) => {
            // 检查请求URL是否以'file://'开头但不是'file:///'(即非标准本地文件路径)
            if (details.url.startsWith('file://') && !details.url.startsWith('file:///')) {
                // 从环境变量获取基础URL(通常由Vite注入)
                const fullUrl = import.meta.env.VITE_AXIOS_BASE_URL

                // 将基础URL解析为URL对象以便获取协议部分
                const urlObj = new URL(fullUrl)

                // 替换原URL中的'file:'协议为环境变量中的协议(如http:或https:)
                const newUrl = details.url.replace('file:', urlObj.protocol)

                // 执行回调进行重定向
                return callback({ redirectURL: newUrl })
            }

            // 对于不符合条件的请求,正常放行
            return callback({})
        }
    )

    // 创建主窗口
    createWindow()

    // macOS特有行为:当应用被激活但没有窗口时创建新窗口
    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) {
            createWindow()
        }
    })
})

// 监听所有窗口关闭事件(仅限macOS不退出应用)
app.on('window-all-closed', () => {
    // 非macOS平台(如Windows/Linux)直接退出应用
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

步骤 3:创建预加载脚本(可选)
新建 electron/preload.ts 文件:

language 复制代码

步骤 4:创建 vite 插件
新建 plugins/vite.electron.build.ts 文件:

language 复制代码
import type { Plugin } from 'vite'
import path from 'path'
import fs from 'fs'

/**
 * Vite 插件:为 Electron 构建优化
 * 在构建完成后执行以下操作:
 * 1. 修改 package.json 的入口文件为 'main.js'
 * 2. 将修改后的 package.json 写入到 dist 目录
 * 3. 在 dist 目录创建 node_modules 空目录(Electron 应用需要)
 */
export const viteElectronBuild = (): Plugin => {
    return {
        // 插件名称
        name: 'vite-electron-build',

        /**
         * Vite 构建完成时的钩子函数
         * 在打包结束后自动执行
         */
        closeBundle: () => {
            // 读取项目根目录的 package.json
            const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'))

            // 构建精简版 package.json
            const distPkg: Record<string, string> = {
                name: packageJson.name,
                version: packageJson.version,
                main: 'main.js', // Electron 入口文件
            }

            if (packageJson.description) {
                distPkg.description = packageJson.description
            }
            if (packageJson.author) {
                distPkg.author = packageJson.author
            }
            if (packageJson.homepage) {
                distPkg.homepage = packageJson.homepage
            }

            // 将修改后的 package.json 写入到 dist 目录
            const distPackagePath = 'dist/package.json'
            fs.writeSync(
                fs.openSync(distPackagePath, 'w'), // 同步打开/创建文件
                JSON.stringify(distPkg, null, 2) // 带缩进的格式化输出
            )

            // 在 dist 目录创建 node_modules 文件夹
            // (某些 Electron 应用依赖此目录结构)
            const nodeModulesPath = path.join(process.cwd(), 'dist/node_modules')
            fs.mkdirSync(nodeModulesPath)
        },
    }
}

步骤 5:创建 Electron 打包配置文件
新建 electron-builder.json 文件:

language 复制代码
{
    "appId": "com.buildadmin.app",
    "productName": "BuildAdmin",
    "directories": {
        "output": "release",
        "app": "dist"
    },
    "nsis": {
        "oneClick": false,
        "allowToChangeInstallationDirectory": true
    },
    "electronDownload": {
        "mirror": "https://npmmirror.com/mirrors/electron/"
    },
    "asar": true,
    "win": {
        "target": "nsis",
        "icon": "public/favicon.ico"
    },
    "mac": {
        "target": "dmg",
        "icon": "public/favicon.png"
    },
    "linux": {
        "target": "AppImage",
        "icon": "public/favicon.png"
    }
}

步骤 6:配置 Vite 插件
在 vite.config.ts 中添加 Electron 插件:

language 复制代码
import electron from 'vite-plugin-electron'
import { viteElectronBuild } from './plugins/vite.electron.build'

plugins: [
            vue(),
            // 在此处新增 electron viteElectronBuild
            electron([
                {
                    entry: 'electron/main.ts',
                    vite: { build: { outDir: 'dist' } },
                },
                {
                    entry: 'electron/preload.ts',
                    vite: { build: { outDir: 'dist' } },
                },
            ]),
            viteElectronBuild(),
            svgBuilder('./src/assets/icons/'),
            customHotUpdate(),
        ],

步骤 7:修改 package.json
添加 Electron 构建配置:

language 复制代码
{
    "main": "dist/main.js",
    "scripts": {
        "build": "vite build && esno ./src/utils/build.ts && electron-builder",
    }
}

步骤 8:修改 .env.production
将原来的 '/' 改为 './'

language 复制代码
# base路径
VITE_BASE_PATH = './'

步骤 9:运行与构建
开发模式:

language 复制代码
npm run dev

生产构建:

language 复制代码
npm run build

最终项目结构

language 复制代码
web/
├── electron/
│   ├── main.ts                 # Electron 主进程
│   └── preload.ts              # 预加载脚本
├── plugins/
│   └── vite.electron.build.ts  # Vite 插件
├── release/                    # Electron 编译目录
├── src/                        # BuildAdmin 源码
├── .env.production             # 生产环境变量定义
├── electron-builder.json       # Electron 打包配置
├── package.json
└── vite.config.ts              # Vite 配置

需要解决两个关键点:

1. 生产模式下,由于使用 win.loadFile('index.html') 可能导致以 "//" 开头的协议(即相对协议)被解析为file://,从而引起头像等资源加载失败(因为头像是http/https资源)

可以改用 win.loadURL(import.meta.env.VITE_AXIOS_BASE_URL) 或者在 BuildAdmin 框架需要修改的页面中使用 fullUrl() 补全协议

2. public 目录下的 favicon.ico 尺寸要求:必须为 256x256 像素

当执行 npm install 或类似命令安装 Electron 时,常见以下错误提示:

language 复制代码
Electron failed to install correctly, please delete node_modules/electron and try installing again

或卡在 node install.js 步骤长时间不动。这通常是由于 node_modules/electron 目录中的文件丢失或损坏导致程序无法正常执行。

解决方案:使用 electron-fix 工具

language 复制代码
# 1. 首先正常安装项目依赖
npm install

# 2. 全局安装 electron-fix 工具
npm install -g electron-fix

# 3. 在项目根目录执行修复
electron-fix start

# 4. 重新运行项目
npm run dev
1个回答默认排序 投票数排序
YANG001
YANG001
这家伙很懒,什么也没写~
4天前

感谢分享~

请先登录
0
1
0
1