Electron 与 Vue3 桌面应用开发指南

Viewed 0

Electron 入门:从背景到 Vue3 桌面应用开发

前言

Electron 是一个开源框架,由 GitHub 开发,允许开发者使用 Web 技术(HTML、CSS、JavaScript)构建跨平台桌面应用程序。其核心组成可概括为:Chromium 提供强大的渲染引擎负责界面显示,Node.js 提供后端能力如文件系统和网络访问,Native APIs 则提供操作系统级别的功能如菜单、通知和托盘。

一、Electron 背景介绍

1. 起源与发展

Electron 最初名为 Atom Shell,是 GitHub 为其 Atom 编辑器项目在 2013 年开发的底层框架。2015 年更名为 Electron 并开源,随后被 Slack、Visual Studio Code、Discord 等知名应用采用。2022 年,底层升级至 Chromium 106 和 Node.js 16.16.0,并支持 Windows 沉浸式黑暗模式等新特性。

2. 核心特点

Electron 将 Chromium(浏览器内核)和 Node.js(服务器/系统能力)封装进一个桌面应用壳中,使开发者能够使用 HTML/CSS/JS 编写跨平台的桌面程序(支持 Windows、macOS、Linux)。其关键特点包括:

  • 跨平台:一套代码可运行在 Windows、macOS、Linux 上。
  • Web 技术驱动:使用 HTML、CSS、JavaScript 构建 UI,无需学习 C++、Objective-C 或 Java。
  • Chromium + Node.js 结合:Chromium 提供现代化的 Web 渲染引擎(支持最新 Web API),Node.js 允许访问文件系统、网络、原生 API 等底层功能。
  • 生态丰富:支持自动更新、打包安装(如 NSIS、DMG、AppImage),并被 VS Code、Figma、Trello Desktop 等流行应用使用。

3. 优势

Electron 的设计理念是“一次编写,到处运行”。主要优势包括:

  • 上手快速:Web 开发者可以复用前端技能、组件和生态(如 React、Vue、Angular、TypeScript、CSS)。
  • 跨平台支持:编写一次代码即可构建三个平台的应用程序。
  • 强大的本地能力:直接访问文件系统、进程、系统 API,无需编写本地语言绑定。
  • 生态成熟:拥有大量现成库、模板和打包工具(如 Electron Builder、Electron Forge)。
  • 适合工具类应用:如编辑器、通信工具、生产力软件和调试工具。

4. 应用场景

典型应用场景包括开发工具/编辑器(如 VS Code、Postman)、即时通信/社交客户端(如 Discord、Slack)、跨平台桌面客户端、原型与内部工具(如公司内部运营工具和数据面板)。它不适合对 CPU/GPU/内存极度敏感、需要极致原生体验或移动端优先的项目。

5. Electron 能做什么

Electron 能够实现多种功能,例如打开窗口、菜单、系统托盘和通知;读写文件、操作本地数据库;调用本机命令、启动子进程;使用原生对话框、剪贴板、拖拽和全局快捷键;实现自动更新、热重载和打包分发;加载本地或远程网页,支持现代 Web 技术(如 WebGL、WebRTC);以及集成原生模块以接入硬件或系统功能。

二、Electron 架构

Electron 应用基于多进程架构,主要包括:

1. 主进程(Main Process)

主进程是 Electron 应用的入口,负责控制应用生命周期(启动、退出)、创建窗口和管理原生功能(如菜单、对话框)。它运行在 Node.js 环境中,使用 Electron API,关键模块包括 app(控制应用事件)、BrowserWindow(创建窗口)、dialog(文件/消息对话框)和 ipcMain(与渲染进程通信)。

2. 渲染进程(Renderer Process)

每个 BrowserWindow 对应一个渲染进程,负责 UI 渲染(HTML/CSS/JS),类似于浏览器标签页。它运行在 Chromium 环境中,支持 Web 技术,关键模块包括 ipcRenderer(与主进程通信)和 fetch/XMLHttpRequest(网络请求)。

进程通信(IPC):主进程和渲染进程通过 ipcMainipcRenderer 进行数据交换。安全注意事项包括:永远不要在渲染进程中直接开启 NodeIntegration(应设置为 nodeIntegration: false),默认关闭以防 XSS 导致任意系统命令执行;使用 contextIsolation + preload + contextBridge 暴露最小、受控的 API;对外部内容进行严格校验和沙箱处理;对文件路径、shell 命令等输入做严格校验以避免命令注入;尽量使用 CSP、禁用 eval 并避免不受信任的第三方脚本。

三、环境搭建(Vue3 + Electron)

1. 创建 Vue3 项目

使用 Vite 创建 Vue3 项目:

npm create vite@latest my-vue-electron-app -- --template vue
cd my-vue-electron-app
npm install

2. 安装 Electron 依赖

安装 Electron 和打包工具:

npm install electron --save-dev
npm install electron-builder --save-dev

3. 项目结构

项目基本结构如下:

my-vue-electron-app/
├── package.json
├── vite.config.js
├── src/          # Vue3 前端代码
├── main.js       # Electron 主进程
├── preload.js    # 预加载脚本(安全 IPC 通信)
└── index.html    # Electron 渲染进程入口(可选)

四、配置 Electron 主进程

1. 创建 main.js(主进程)

在项目根目录创建 main.js,用于控制 Electron 窗口和 Vue3 应用:

const { app, BrowserWindow } = require('electron');
const path = require('path');

function createWindow() {
  const win = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      nodeIntegration: false, // 禁用 Node.js 集成(安全考虑)
      contextIsolation: true, // 启用上下文隔离
      preload: path.join(__dirname, 'preload.js'), // 预加载脚本
    },
  });

  // 开发环境加载 Vite 开发服务器
  if (process.env.NODE_ENV === 'development') {
    win.loadURL('http://localhost:5173');
    win.webContents.openDevTools(); // 打开 DevTools(可选)
  } else {
    // 生产环境加载打包后的 Vue3 应用
    win.loadFile(path.join(__dirname, '../dist/index.html'));
  }
}

// Electron 初始化完成后创建窗口
app.whenReady().then(createWindow);

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

// macOS 点击 Dock 图标时重新创建窗口
app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) createWindow();
});

2. 创建 preload.js(预加载脚本)

用于安全地暴露 IPC 通信 API 给 Vue3 渲染进程:

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  // 示例:发送消息到主进程
  sendMessage: (message) => ipcRenderer.send('message-from-vue', message),
  // 示例:接收主进程消息
  onMessage: (callback) => ipcRenderer.on('message-from-main', (event, data) => callback(data)),
});

五、配置 Vue3 与 Electron 通信

1. 在 Vue3 组件中使用 IPC

在 Vue3 组件(如 src/App.vue)中调用 Electron API:

<template>
  <div>
    <h1>Vue3 + Electron 桌面应用</h1>
    <button @click="sendMessageToElectron">发送消息给 Electron</button>
    <div v-if="messageFromElectron">
      <p>来自 Electron 的消息: {{ messageFromElectron }}</p>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const messageFromElectron = ref('');

// 发送消息到 Electron 主进程
const sendMessageToElectron = () => {
  window.electronAPI.sendMessage('Hello from Vue3!');
};

// 接收来自 Electron 的消息
onMounted(() => {
  window.electronAPI.onMessage((data) => {
    messageFromElectron.value = data;
  });
});
</script>

2. 在 main.js 中处理 IPC 消息

修改 main.js,让 Electron 主进程接收并回复 Vue3 的消息:

const { ipcMain } = require('electron');

// 监听来自 Vue3 的消息
ipcMain.on('message-from-vue', (event, message) => {
  console.log('来自 Vue3 的消息:', message);
  // 回复消息给 Vue3
  event.sender.send('message-from-main', 'Electron 收到你的消息了!');
});

六、打包 Vue3 + Electron 应用

1. 修改 package.json

package.json 中添加或修改相关配置:

{
  "name": "my-vue-electron-app",
  "version": "1.0.0",
  "main": "main.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:5173 && electron .\"",
    "electron:build": "npm run build && electron-builder"
  },
  "devDependencies": {
    "electron": "^28.0.0",
    "electron-builder": "^24.0.0",
    "concurrently": "^8.0.0",
    "wait-on": "^7.0.0"
  },
  "build": {
    "appId": "com.example.vue-electron",
    "productName": "Vue3 Electron App",
    "win": { "target": "nsis" },
    "mac": { "target": "dmg" },
    "linux": { "target": "AppImage" }
  }
}

2. 运行与打包

  • 开发模式:运行 npm run electron:dev 同时启动 Vue3 开发服务器和 Electron。
  • 生产打包:运行 npm run electron:build,打包后在 dist/ 文件夹中生成 Windows .exe、macOS .dmg 和 Linux .AppImage 安装包。

七、总结

本文介绍了 Electron 的背景、架构、环境搭建、配置通信和打包流程。关键步骤包括:使用 Vue3 创建前端项目,集成 Electron 主进程和预加载脚本以实现安全 IPC 通信,并通过 electron-builder 打包成跨平台安装包。开发时注意安全最佳实践,如禁用 nodeIntegration、使用 contextIsolation 和 contextBridge。

0 Answers