当前位置: 首页 > news >正文

electron系列1:Electron不是玩具,为什么桌面应用需要它?

一、一个前端工程师的困惑

2018年,我第一次听到Electron,当时的反应和很多人一样:

“用网页技术写桌面应用?这不就是套个浏览器壳子吗?能好用吗?”

这个偏见在很长时间里影响了我。直到后来,我发现自己每天都在用的VSCode、Slack、Figma、Notion,竟然都是Electron写的。

如果这些产品都在用,那一定不只是“套壳”那么简单。

二、Electron到底是什么?

官方的定义很简洁:

Electron是一个使用JavaScript、HTML和CSS构建跨平台桌面应用程序的框架。

但这句话太抽象了。让我们用一张图来看清楚Electron的架构:

我更喜欢用这个公式来理解它:

Electron = Chromium + Node.js + 原生API

拆开来看:

组成部分作用通俗解释代码示例
Chromium渲染界面用你熟悉的HTML/CSS/JS画界面divbuttonflexbox
Node.js调用系统能力读写文件、执行命令、访问数据库fs.readFile()child_process.exec()
原生API桌面集成系统托盘、全局快捷键、通知TrayglobalShortcutNotification

Electron不是“套壳浏览器”,而是让前端代码获得了接近原生应用的系统能力。

三、一个最小Electron应用长什么样?

让我们写一个最简单的Electron应用,来感受它到底做了什么:

项目结构

my-electron-app/ ├── package.json ├── main.js # 主进程 ├── preload.js # 预加载脚本(安全桥接) └── index.html # 渲染进程(页面)

1. package.json

{ "name": "my-electron-app", "version": "1.0.0", "main": "main.js", "scripts": { "start": "electron ." }, "devDependencies": { "electron": "^28.0.0" } }

2. main.js(主进程)

const { app, BrowserWindow } = require('electron') const path = require('path') // 创建窗口的函数 const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js'), // 预加载脚本 contextIsolation: true, // 开启上下文隔离(安全必须) nodeIntegration: false // 禁止渲染进程直接访问Node(安全必须) } }) win.loadFile('index.html') // 打开开发者工具(开发时使用) // win.webContents.openDevTools() } // 应用准备就绪后创建窗口 app.whenReady().then(() => { createWindow() // macOS:点击dock图标时如果没有窗口就创建一个 app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) // 所有窗口关闭时退出应用(除了macOS) app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit() })

3. preload.js(预加载脚本 - 安全桥接)

const { contextBridge, ipcRenderer } = require('electron') // 安全地暴露API给渲染进程 contextBridge.exposeInMainWorld('electronAPI', { // 读取文件(调用主进程的Node能力) readFile: (filePath) => ipcRenderer.invoke('read-file', filePath), // 保存文件 saveFile: (filePath, content) => ipcRenderer.invoke('save-file', filePath, content), // 获取系统信息 getSystemInfo: () => ipcRenderer.invoke('get-system-info') })

4. index.html(渲染进程 - 这就是普通的Web页面!)

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>我的第一个Electron应用</title> <style> body { font-family: system-ui, -apple-system, sans-serif; margin: 0; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; } .container { text-align: center; padding: 40px; } button { background: white; border: none; padding: 12px 24px; font-size: 16px; border-radius: 8px; cursor: pointer; margin: 10px; transition: transform 0.2s; } button:hover { transform: scale(1.05); } pre { background: rgba(0,0,0,0.3); padding: 15px; border-radius: 8px; text-align: left; overflow-x: auto; } </style> </head> <body> <div class="container"> <h1>欢迎使用Electron</h1> <p>这是一个真正的桌面应用!</p> <button id="systemBtn">获取系统信息</button> <button id="fileBtn">读取文件</button> <div id="output"> <pre>点击按钮,结果会显示在这里...</pre> </div> </div> <script> // 调用通过preload暴露的API const output = document.getElementById('output') document.getElementById('systemBtn').onclick = async () => { // 注意:这里可以直接调用桌面能力! const info = await window.electronAPI.getSystemInfo() output.innerHTML = `<pre>${JSON.stringify(info, null, 2)}</pre>` } document.getElementById('fileBtn').onclick = async () => { // 这里调用的是Node.js的文件读取能力 const content = await window.electronAPI.readFile('package.json') output.innerHTML = `<pre>${content}</pre>` } </script> </body> </html>

关键理解:index.html里的代码看起来就是普通前端代码,但它能调用window.electronAPI.getSystemInfo()——这是纯Web页面做不到的。

四、那些你不知道的Electron产品

很多人用了很久都不知道这些产品是Electron写的:

产品类型日活/用户量为什么选Electron
Visual Studio Code代码编辑器1500万+需要Web技术生态 + 性能要求高
Figma设计工具400万+实时协作能力(WebSocket)+ 跨平台
Notion笔记应用1亿+用户富文本编辑器 + 快速迭代
Slack企业通讯1200万+日活与Web版本复用代码
Discord游戏语音1.5亿+用户低延迟通信 + 游戏内覆盖层
1Password密码管理1500万+跨平台一致性 + 安全性可控
GitHub DesktopGit客户端数百万与GitHub生态无缝集成

这些产品的共同点:

  • 需要快速迭代(Web技术开发效率高)

  • 需要跨平台(Windows/macOS/Linux一套代码)

  • 对界面交互有较高要求(CSS动画、Canvas渲染)

  • 有Web版本,代码复用率高

五、Electron vs 传统方案:选型决策表

这是我给团队做技术选型时用的决策矩阵:

维度ElectronQt/C++WPF/C#JavaFXTauri (Rust)
开发效率⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
运行时性能⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
内存占用~80MB起步~20MB~30MB~40MB~10MB
安装包大小~70MB~5MB~10MB~40MB~2MB
跨平台⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
原生体验⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
社区生态⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
学习成本⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

注:Tauri是较新的替代方案,使用系统WebView而非Chromium,体积更小但兼容性略弱。

决策流程图

决策建议:

  • 选Electron:需要快速迭代、跨平台、有Web技术栈积累

  • 选Qt/C++:需要极致性能(游戏引擎、CAD软件)、或嵌入式设备

  • 选WPF:只做Windows、有C#技术栈、需要深度系统集成

  • 选Tauri:追求小体积、团队熟悉Rust、不需要老平台支持

六、Electron的三大核心优势

优势1:Web技术栈的杠杆效应

前端生态的价值:

  • Vue、React、Svelte等框架直接可用

  • npm上有200万+的包可以直接调用

  • 任何Web组件都可以变成桌面功能

代码复用率示意:

一个真实案例:
我们团队曾需要给桌面应用增加Markdown编辑器。如果用Qt实现,需要数周。但Electron下,直接用@toast-ui/vue-editor,两小时就集成完毕。

优势2:真正的跨平台

Electron一套代码可以生成:

平台输出格式分发渠道
Windows.exe.msi官网下载、Microsoft Store
macOS.dmg.app.pkg官网下载、Mac App Store
Linux.deb.rpm.AppImageAPT、Snap Store、Flathub

平台差异处理示例:

// 同一个代码,自动适配不同平台 const { app } = require('electron') // 文件路径分隔符 const configPath = app.getPath('userData') // Windows: C:\Users\用户名\AppData\Roaming\应用名 // macOS: /Users/用户名/Library/Application Support/应用名 // Linux: /home/用户名/.config/应用名 // 菜单栏差异 if (process.platform === 'darwin') { // macOS:应用菜单在屏幕左上角 app.dock.show() } else { // Windows/Linux:菜单在窗口内 win.setMenu(menu) }

优势3:Web与原生能力的无感融合

这是Electron最强大的地方——你可以在同一个代码文件中写:

// 这是一个完整的Electron功能片段 document.getElementById('save').addEventListener('click', async () => { const content = editor.getValue() // 1. 这是Web代码(DOM操作) document.getElementById('status').innerText = '保存中...' // 2. 这是Node.js代码(写文件) await fs.promises.writeFile(currentFilePath, content) // 3. 这是原生能力(系统通知) new Notification('保存成功', { body: `文件已保存到 ${currentFilePath}`, icon: 'icon.png' }) // 4. 这是Electron原生API(闪烁任务栏图标) win.flashFrame(true) // 5. 更新UI document.getElementById('status').innerText = '已保存' })

前端开发者不需要学习C++、不需要了解Win32 API,就能实现完整的桌面应用。

七、Electron的三大缺点(以及如何应对)

作为资深开发者,我必须诚实地说出它的痛点:

缺点1:内存占用高

问题图示:

应对方案代码:

// 方案1:后台窗口节流 const win = new BrowserWindow({ webPreferences: { backgroundThrottling: true // 后台窗口降低帧率和定时器频率 } }) // 方案2:窗口销毁时彻底释放 win.on('closed', () => { win = null // 解除引用,让GC回收 }) // 方案3:使用内存分析工具 // 在Chrome DevTools中 Memory -> Take heap snapshot // 找出未释放的对象

缺点2:安装包体积大

体积对比:

应用安装包大小安装后大小
原生记事本<1MB<1MB
Qt计算器~5MB~15MB
最小Electron应用~70MB~180MB
典型Electron应用100-200MB300-500MB

应对方案:

// electron-builder配置 - 启用最大压缩 { "build": { "compression": "maximum", // 使用7z压缩,比zip小30% "asar": true, // 打包成asar格式 "files": [ "!**/*.map", // 排除source map "!**/test/**", // 排除测试文件 "!**/docs/**" // 排除文档 ] } }

缺点3:启动速度慢

启动流程耗时分析:

优化方案代码:

// 方案1:先创建隐藏窗口 let win = new BrowserWindow({ show: false, // 先隐藏 webPreferences: { preload } }) win.loadURL('app://index.html') // 准备就绪后再显示 win.once('ready-to-show', () => { win.show() // 如果有需要,再打开DevTools // if (isDev) win.webContents.openDevTools() }) // 方案2:缓存编译结果 // 安装 v8-compile-cache require('v8-compile-cache') // 方案3:预创建常用窗口(VSCode模式) class WindowManager { constructor() { this.pendingWindows = [] } preCreate() { // 后台提前创建常用窗口 const win = new BrowserWindow({ show: false }) this.pendingWindows.push(win) } getWindow() { if (this.pendingWindows.length > 0) { const win = this.pendingWindows.pop() win.show() return win } return new BrowserWindow() } }

八、什么时候应该(不应该)用Electron?

✅ 适合使用Electron的场景

典型适用案例:

  1. 已有Web版本的产品

    • 直接复用70%+的代码

    • Slack、Discord、Figma都是这么做的

  2. 需要跨平台的工具类应用

    • Markdown编辑器、API测试工具、数据库客户端

    • 例:Postman、TablePlus、Beekeeper Studio

  3. 对界面交互要求高

    • 需要复杂动画、实时协作、Canvas绘图

    • Electron可以使用任何Web动画技术

  4. 快速迭代的创业产品

    • Web前端可以直接转型桌面开发

    • 无需招聘C++/C#团队

❌ 不适合使用Electron的场景

九、Electron vs Tauri:新生代挑战者

近年来Tauri成为热门替代方案,这里做一个详细对比:

对比维度ElectronTauri
后端语言Node.jsRust
前端技术任意Web框架任意Web框架
WebView内置Chromium系统原生WebView
安装包大小~70MB起步~2MB起步
内存占用~80MB起步~10MB起步
Windows 7支持✅ 完全支持⚠️ 需要WebView2
API丰富度⭐⭐⭐⭐⭐⭐⭐⭐
生态成熟度⭐⭐⭐⭐⭐⭐⭐⭐
学习成本低(前端可上手)中(需要了解Rust)

选型建议:

  • 追求最小体积+ 团队有Rust能力 → 选Tauri

  • 需要最大兼容性+ 团队纯前端 → 选Electron

  • 需要丰富API+ 快速开发 → 选Electron

十、Electron的学习路线图

如果决定学习Electron,建议按这个路径:

十一、写在最后:Electron的定位

Electron不是银弹,也不是玩具。

它是一个务实的选择——让Web技术栈的团队能够以可接受的性能和体积代价,交付跨平台桌面应用。

什么时候应该认真考虑Electron?

当你的团队以Web前端为主,当你需要在3-6个月内交付桌面产品,当你愿意用200MB安装包换取80%的代码复用率时,Electron就是最佳答案。

数据支撑:

  • GitHub上Electron有110k+ star

  • 每周npm下载量超过1000万次

  • 全球有超过100万个Electron应用

  • VSCode证明了它可以做到极致性能

  • Figma证明了它可以承载复杂交互

  • Notion证明了它适合现代SaaS产品

http://www.jsqmd.com/news/617557/

相关文章:

  • ComfyUI ControlNet Aux预处理器:如何用45种AI工具突破图像控制的极限?
  • 艾默生EMU10-DY电源模块
  • 泛微Ecology9全栈二开实战:从零构建增删改查模块(后端Action+前端Ecode)
  • 双非逆袭上岸985~
  • 5分钟学会BabelDOC:让专业文档翻译不再丢失格式的终极指南
  • Lite-Avatar与GitHub Actions的CI/CD实践
  • 如何用JPEXS Free Flash Decompiler轻松反编译SWF文件:完整指南
  • 算力的本质:从 GPU 到“算力系统”,一文讲透大模型背后的硬件逻辑
  • 【C++】设计一个单例基类,用户使用基类提供 getInstance() 来获取派生类实例化的单例对象
  • 如何让OBS视频成为Windows应用的标准摄像头?OBS-VirtualCam深度解析
  • 3种颠覆性方式重新定义AI与浏览器的对话边界
  • 私有云部署实操:从零搭建企业内部云平台
  • 汽车电子EMC测试:RE试验与BCI整改实战解析
  • Qwen3.5-9B多卡并行教程:DeepSpeed Zero-3模型切分部署
  • Windows版Poppler终极安装指南:5分钟搞定PDF处理工具
  • Windows 11 24H2 LTSC 如何三步恢复微软商店?让精简系统重获完整应用生态的终极方案
  • StructBERT中文模型实战:GPU算力高效利用——单卡3090实测并发16路语义匹配
  • linux起源与哲学
  • 如何快速掌握PlugY:暗黑破坏神2单机玩家的终极生存指南
  • 温度参数调优:OpenClaw+Qwen3-4B不同任务下的creativity设置
  • 低成本AI部署新选择:Gemma-3-270m适配Jetson Nano边缘设备实测
  • 互联网大厂为啥不把研发迁到二三线城市?
  • OpenClaw白话讲解:AI如何从会聊天变成会干活
  • 桌面端 Claw 个人微信接入指南杆
  • RAG笔记——架构及检索方式
  • 查老板查企业:合法避坑指南+高效工具推荐
  • 深入解析 NVIDIA 显卡中 FP16 Tensor Core 与 FP16 算力的性能差异与应用场景
  • 手机卡就是SIM卡吗?真相揭秘
  • 揭秘!中国八大软件外包公司
  • Windows11 ARM系统直接运行X86 exe,高通CPU同时运行安卓APP,任意软件