最近,想弥补自己在桌面端应用这块的空白,去了解了一下相关的应用技术,最后调研出了如下结果
桌面端框架选型对比
| 框架 | 性能 | 包体积 | 安全性 | 开发效率 | 跨平台能力 | 学习成本 | 生态与社区 |
|---|---|---|---|---|---|---|---|
| Native | 非常高 | 非常小 | 非常安全 | 低 | 不跨平台 | 很高 | 中 |
| Qt | 非常高 | 小 | 高 | 中 | 跨平台 | 高 | 强 |
| Tauri | 高 | 很小 | 高 | 高 | 跨平台 | 中 | 中等偏小 |
| Flutter | 高 | 中 | 高 | 中 | 跨平台 | 中 | 强 |
| NW.js | 中 | 大 | 中 | 高 | 跨平台 | 低 | 较小 |
| Electron | 中 | 大 | 中 | 非常高 | 跨平台 | 低 | 非常强 |
最后,经过评估,最终还是选择Electron作为我在这个领域的第一次试手 架构:Chromium + Node.js 优点:Web开发及其友好、生态巨大,成熟稳定 缺点:包体积大、内存占用高
典型应用:Visual Studio Code,桌面端微信,桌面端钉钉等.
一、框架分析
其技术组成如下: Electron=Chromium+Node.js+Native API 整体框架图大概如图下所示
Electron是多进程架构,架构具有以下特点:
- 由一个主进程和N个渲染进程组成
- 由主进程承担主导作用,用于完成各种跨平台和原生交互
- 渲染进程可以是多个,使用Web技术开发,通过浏览器内核渲染页面
- 主进程和渲染进程通过进程间通信(IPC)来完成各种功能
二、使用
纸面信息介绍完了,来实战跑一个小demo,当然出于个人兴趣爱好,我没有跑一个helloworld就止步了,而是做了一个小小的价格监控模块(最近美伊打仗,黄金涨的还挺高,所以写了一个小功能用来监控黄金的价格)
下面是我的项目目录
是不是还挺像那么回事哈哈,其实核心要点就是
main文件夹下核心index.ts主文件进程
import
import path from 'path'
import { initDB } from './db'
import { registerIPC } from './ipc'
import { startScheduler } from './scheduler'
import { readConfig } from './config'
export async function applyProxy(): Promise<void> {
const { proxyUrl } = readConfig()
if (proxyUrl) {
await session.defaultSession.setProxy({ proxyRules: proxyUrl })
console.log(`[Proxy] Applied: ${proxyUrl}`)
} else {
await session.defaultSession.setProxy({ proxyRules: 'direct://' })
console.log('[Proxy] Direct connection (no proxy)')
}
}
let mainWindow: BrowserWindow | null = null
function createWindow(): void {
mainWindow = new BrowserWindow({
width: 1000,
height: 700,
webPreferences: {
preload: path.join(__dirname, '../preload/index.js'),
contextIsolation: true,
nodeIntegration: false
}
})
mainWindow.setTitle('Web3 Monitor')
// electron-vite: dev 时加载 dev server,production 时加载打包文件
if (process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
} else {
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'))
}
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
return { action: 'deny' }
})
}
app.whenReady().then(async () => {
// 1. 初始化数据库
initDB()
// 2. 应用代理设置
await applyProxy()
// 3. 注册 IPC handlers
registerIPC()
// 4. 创建窗口
createWindow()
// 5. 启动定时监控
startScheduler()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
preload文件夹下核心的ipc通信文件,index.ts/ (我个人的心里体会哈:这块就像标准的前后端连调,接口层这,不同的是,这里的通信不需要发http,)
js
import { contextBridge, ipcRenderer } from 'electron'
const api = {
// Token CRUD
getTokens: () => ipcRenderer.invoke('getTokens'),
}
contextBridge.exposeInMainWorld('electronAPI', api)
render代码我这里就不贴出来了,毕竟就是常规的前端代码
最后启动项目后就是一个新开了一个桌面应用一样

三、打包
就如调研的时候,打包真的是个诟病,同一套代码,我试过了mac,windows双平台打包, mac打包的dmg,大小为102.1MB,windows也差不多是这个大小./
如果追求跨端,高性能,低打包体积,建议技术选型还是选择tarui,但就是需要对rust有所了解,下一个桌面端框架笔者就会去研究用用,毕竟打包体积真的很香(嘿嘿)