Electron 桌面应用开发入门,前端也能写客户端

产品经理说"能不能做成桌面应用"。我第一反应是:我又不会 C++/C#。后来发现 Electron 就是给前端准备的------用 HTML/CSS/JS 写桌面应用,VS Code、Discord、Slack 都是这么做的。

基本概念

Electron = Chromium(渲染页面)+ Node.js(系统能力)

scss 复制代码
┌─────────────────────────┐
│       Electron App       │
├──────────┬──────────────┤
│ 主进程    │   渲染进程    │
│ (Node.js)│  (Chromium)  │
│          │              │
│ - 系统API │  - 页面渲染   │
│ - 文件操作 │  - DOM/CSS   │
│ - 菜单    │  - 用户交互   │
│ - 托盘    │              │
└──────────┴──────────────┘
  • 主进程(Main):Node.js 环境,可以操作文件系统、创建窗口、访问系统 API
  • 渲染进程(Renderer):就是浏览器环境,跑你的前端页面

快速开始

bash 复制代码
npm create electron-app@latest my-app
cd my-app
npm start

项目结构:

perl 复制代码
my-app/
├── src/
│   ├── main.js        # 主进程入口
│   ├── preload.js     # 预加载脚本(主进程和渲染进程之间的桥梁)
│   └── renderer/      # 前端页面(可以是 Vue/React 项目)
├── package.json
└── electron-builder.yml

主进程:创建窗口

js 复制代码
// src/main.js
const { app, BrowserWindow, Menu, Tray } = require('electron')
const path = require('path')

let mainWindow = null

app.whenReady().then(() => {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    minWidth: 800,
    minHeight: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,  // 安全:隔离上下文
      nodeIntegration: false,  // 安全:不直接暴露 Node
    }
  })

  // 开发环境加载 localhost,生产环境加载打包后的文件
  if (process.env.NODE_ENV === 'development') {
    mainWindow.loadURL('http://localhost:3000')
    mainWindow.webContents.openDevTools()
  } else {
    mainWindow.loadFile(path.join(__dirname, '../dist/index.html'))
  }
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()  // macOS 关闭窗口不退出应用
  }
})

主进程和渲染进程通信

js 复制代码
// preload.js --- 暴露安全的 API 给渲染进程
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  // 读取文件
  readFile: (filePath) => ipcRenderer.invoke('read-file', filePath),
  // 保存文件
  saveFile: (filePath, content) => ipcRenderer.invoke('save-file', filePath, content),
  // 选择文件夹
  selectFolder: () => ipcRenderer.invoke('select-folder'),
  // 监听主进程消息
  onNotification: (callback) => ipcRenderer.on('notification', (_, data) => callback(data)),
})

// main.js --- 处理渲染进程的请求
const { ipcMain, dialog } = require('electron')
const fs = require('fs/promises')

ipcMain.handle('read-file', async (_, filePath) => {
  return await fs.readFile(filePath, 'utf-8')
})

ipcMain.handle('save-file', async (_, filePath, content) => {
  await fs.writeFile(filePath, content, 'utf-8')
})

ipcMain.handle('select-folder', async () => {
  const result = await dialog.showOpenDialog({ properties: ['openDirectory'] })
  return result.filePaths[0]
})
js 复制代码
// 渲染进程中使用
async function openFile() {
  const content = await window.electronAPI.readFile('/path/to/file.txt')
  console.log(content)
}

async function chooseFolder() {
  const folder = await window.electronAPI.selectFolder()
  console.log('选择了:', folder)
}

系统托盘

js 复制代码
const { app, Tray, Menu } = require('electron')

let tray = null

app.whenReady().then(() => {
  tray = new Tray(path.join(__dirname, 'icon.png'))

  const contextMenu = Menu.buildFromTemplate([
    { label: '显示主窗口', click: () => mainWindow.show() },
    { label: '退出', click: () => app.quit() },
  ])

  tray.setToolTip('我的应用')
  tray.setContextMenu(contextMenu)

  tray.on('click', () => {
    mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show()
  })
})

打包发布

yaml 复制代码
# electron-builder.yml
appId: com.example.myapp
productName: My App
directories:
  output: release
files:
  - dist/**
  - src/main.js
  - src/preload.js
win:
  target: nsis
  icon: build/icon.ico
mac:
  target: dmg
  icon: build/icon.icns
linux:
  target: AppImage
bash 复制代码
# 打包
npm run build       # 先构建前端
npx electron-builder  # 打包桌面应用

输出:Windows 的 .exe 安装包、macOS 的 .dmg、Linux 的 .AppImage。

注意事项

  • 包体积大:Electron 自带 Chromium,最小也有 100MB+。如果在意体积考虑 Tauri(Rust + 系统 WebView)
  • 内存占用高:每个窗口就是一个 Chromium 实例
  • 安全第一 :contextIsolation: true + nodeIntegration: false,不要直接暴露 Node API 给渲染进程
  • 自动更新 :用 electron-updater 实现应用内自动更新

总结

Electron 让前端能写桌面应用,核心就是:主进程管系统能力(文件、菜单、托盘),渲染进程跑前端页面,两者通过 IPC 通信。VS Code、Notion、Figma 桌面版都是 Electron 做的。包体积大是最大缺点,不在意这个的话,前端写桌面应用首选 Electron。

相关推荐
默_笙1 小时前
🚊 别再让 AI 的记忆写两遍了:PostgreSQL 把关系查询和语义检索装进一张表
前端·javascript
进击的明明1 小时前
TypeScript速通笔记(下)
前端·面试·typescript
lzhdim1 小时前
C#不为人知的10个魔法特性:资深开发者也会震惊的底层奥秘
java·前端·javascript·算法·c#
zach2 小时前
前端落地实战:Next.js 项目 Nginx + PM2 生产部署全流程(附踩坑总结)
前端·pm2·next.js
overmind2 小时前
oeasy教h5前端001 修改的乐趣_直接修改在线网页
前端
只睡四小时2 小时前
JS 手写 D-pad 空间导航:电视端焦点引擎实战
android·开发语言·前端·javascript·ecmascript·hls·空间导航
恋猫de小郭3 小时前
Android 原生的 Compose A2UI 也来了,你还抱着 XML 养老吗?
android·前端·flutter
庄园特聘拆椅狂魔3 小时前
从连连看到粒子消散——前端小游戏与视觉特效的技术选型
前端
JudithHuang3 小时前
React 常用 Hooks
前端·react.js·前端框架