杰瑞科技汇

Electron 教程,从零开始怎么学?

Electron 完整教程:从零开始构建跨平台桌面应用

什么是 Electron?

Electron 是一个使用 Web 技术(HTML, CSS, JavaScript)来构建跨平台桌面应用的开源框架

Electron 教程,从零开始怎么学?-图1
(图片来源网络,侵删)

它由 GitHub 开发并维护,著名的应用如 Visual Studio Code、Slack、Discord、Figma、Postman 等都是基于 Electron 构建的。

核心思想: Electron 将 Chromium(Google Chrome 的内核)和 Node.js 打包在一起,你写的代码运行在一个独立的、可定制的“浏览器窗口”中,同时这个窗口又拥有完整的 Node.js API,可以访问操作系统资源(如文件系统、网络、原生通知等)。

架构: Electron 应用由两个主要进程组成:

  1. 主进程

    Electron 教程,从零开始怎么学?-图2
    (图片来源网络,侵删)
    • 这是应用的入口点,运行着 package.jsonmain 字段指定的脚本。
    • 负责创建和管理应用窗口。
    • 管理应用的生命周期(打开、关闭、最小化等)。
    • 是唯一可以与原生操作系统 API 直接交互的进程。
    • 可以使用 Node.js 模块。
  2. 渲染进程

    • 每个应用窗口都有一个对应的渲染进程。
    • 负责渲染用户界面,也就是你的 HTML, CSS, JavaScript 代码。
    • 本质上就是一个独立的 Chrome 浏览器实例。
    • 默认情况下,出于安全考虑,渲染进程不能直接使用 Node.js 模块。
  3. 预加载脚本

    • 这是一个在渲染进程加载之前就加载的脚本,运行在渲染进程的上下文中。
    • 它是连接主进程和渲染进程的安全桥梁,你可以在这里暴露一些主进程的 API 给渲染进程使用,而不会破坏 Electron 的安全模型。

开发环境准备

在开始之前,确保你的电脑上安装了以下工具:

  1. Node.js 和 npm

    Electron 教程,从零开始怎么学?-图3
    (图片来源网络,侵删)
    • 访问 Node.js 官网 下载并安装 LTS(长期支持)版本。
    • 安装完成后,打开终端(命令提示符或 PowerShell)运行以下命令,确认安装成功:
      node -v
      npm -v
  2. 代码编辑器

    • 强烈推荐 Visual Studio Code,它本身就是用 Electron 构建的,对 Electron 开发支持非常好。

第一个 Electron 应用:Hello World

让我们一步步创建一个最简单的 Electron 应用。

步骤 1:初始化项目

  1. 创建一个新的项目文件夹,并进入该文件夹。

    mkdir my-electron-app
    cd my-electron-app
  2. 初始化 npm 项目。-y 参数会接受所有默认设置。

    npm init -y
  3. 安装 Electron。

    # 安装为开发依赖
    npm install electron --save-dev

步骤 2:创建核心文件

在你的项目根目录下,创建以下三个文件:

  1. package.json (已由 npm init 创建,稍作修改)
  2. main.js (主进程入口文件)
  3. index.html (渲染进程的界面)

package.json 修改 main 字段,指向我们的主进程文件 main.js

{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "My first Electron app",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron": "^latest-version" // 这里的版本号会是你安装的版本
  }
}

index.html 一个简单的 HTML 页面。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f0f0f0;
        }
        h1 {
            color: #333;
        }
    </style>
</head>
<body>
    <h1>Hello World from Electron!</h1>
    <p>This is my first Electron application.</p>
</body>
</html>

main.js 这是 Electron 应用的核心,负责创建和管理窗口。

// 引入 Electron 模块
const { app, BrowserWindow } = require('electron');
// 定义一个函数来创建主窗口
function createWindow() {
    // 创建一个浏览器窗口
    const mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            // 预加载脚本,稍后会用到
            preload: path.join(__dirname, 'preload.js')
        }
    });
    // 加载应用的 index.html
    mainWindow.loadFile('index.html');
    // (可选)打开开发者工具,方便调试
    // mainWindow.webContents.openDevTools();
}
// Electron 会在初始化完成并准备好创建浏览器窗口时调用这个函数
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(createWindow);
// 当所有窗口都关闭时退出应用
app.on('window-all-closed', () => {
    // 在 macOS 上,通常应用和它们的菜单栏会保持活跃
    // 直到用户使用 Cmd + Q 明确退出
    if (process.platform !== 'darwin') {
        app.quit();
    }
});
app.on('activate', () => {
    // 在 macOS 上,当点击 dock 图标并且没有其他窗口打开时
    // 通常会重新创建一个窗口
    if (BrowserWindow.getAllWindows().length === 0) {
        createWindow();
    }
});

注意:上面的 main.js 使用了 path 模块,所以需要在文件顶部引入它:

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

步骤 3:运行应用

回到你的终端,运行 npm start 命令:

npm start

如果一切顺利,你将看到一个包含 "Hello World from Electron!" 文本的窗口,恭喜你,你已经成功运行了第一个 Electron 应用!


进阶:进程间通信

我们来实现一个常见的需求:点击 HTML 按钮,让主进程执行一个操作(比如选择文件)

这需要用到预加载脚本

步骤 1:创建 preload.js

在项目根目录创建 preload.js 文件。

// 在预加载脚本中,我们可以使用 Electron 的 contextBridge 模块
// 安全地将一些 API 从主进程暴露给渲染进程
const { contextBridge, ipcRenderer } = require('electron');
// 将 ipcRenderer 暴露给渲染进程的全局 window 对象
contextBridge.exposeInMainWorld('electronAPI', {
    // 暴露一个选择文件的函数
    selectFile: () => ipcRenderer.send('dialog:openFile')
});

步骤 2:修改 main.js

更新主进程,让它监听来自渲染进程的消息,并执行操作。

const path = require('path');
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
function createWindow() {
    const mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            // 指定预加载脚本
            preload: path.join(__dirname, 'preload.js')
        }
    });
    mainWindow.loadFile('index.html');
}
app.whenReady().then(createWindow);
// 监听来自渲染进程的 'dialog:openFile' 事件
ipcMain.on('dialog:openFile', async (event) => {
    const result = await dialog.showOpenDialog({
        properties: ['openFile', 'multiSelections'],
        filters: [
            { name: 'Images', extensions: ['jpg', 'png', 'gif'] }
        ]
    });
    // 如果用户选择了文件,将文件路径发回给渲染进程
    if (!result.canceled) {
        event.sender.send('dialog:fileSelected', result.filePaths);
    }
});
// ... (app.on('window-all-closed') 和 app.on('activate') 代码保持不变)

步骤 3:修改 index.html

更新 HTML,添加一个按钮,并添加 JavaScript 来处理点击事件和接收主进程的响应。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">IPC Demo</title>
    <style>
        body { font-family: sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; }
        button { padding: 10px 20px; font-size: 16px; cursor: pointer; }
        #file-info { margin-top: 20px; word-break: break-all; }
    </style>
</head>
<body>
    <h1>进程间通信演示</h1>
    <button id="select-file-btn">选择文件</button>
    <div id="file-info"></div>
    <script>
        const selectFileBtn = document.getElementById('select-file-btn');
        const fileInfoDiv = document.getElementById('file-info');
        // 监听按钮点击事件
        selectFileBtn.addEventListener('click, () => {
            // 调用在 preload.js 中暴露的 electronAPI.selectFile
            window.electronAPI.selectFile();
        });
        // 监听来自主进程的 'dialog:fileSelected' 事件
        // 注意:这里使用 window.addEventListener 是因为主进程使用 event.sender.send 发送消息
        window.addEventListener('dialog:fileSelected', (event) => {
            const filePaths = event.detail;
            fileInfoDiv.innerHTML = `你选择了文件:<br>${filePaths.join('<br>')}`;
        });
    </script>
</body>
</html>

再次运行 npm start,现在你可以点击按钮,系统会弹出文件选择对话框,选择文件后,文件路径会显示在页面上。


打包应用

开发完成后,你需要将应用打包成可执行文件,以便在没有安装 Node.js 的电脑上运行。

推荐工具:Electron Forge 或 Electron Builder

这里以 Electron Forge 为例,它集成了创建、打包、发布等功能,非常方便。

步骤 1:安装 Electron Forge

# 安装 Electron Forge
npm install electron-forge --save-dev
# 初始化 Electron Forge,它会自动检测你的项目并配置好
npx electron-forge import

步骤 2:配置 package.json

electron-forge import 会修改你的 package.json,添加 make 脚本。

{
  // ... 其他配置
  "config": {
    "forge": {
      "packagerConfig": {},
      "makers": [
        {
          "name": "@electron-forge/maker-squirrel",
          "platforms": ["win32"]
        },
        {
          "name": "@electron-forge/maker-zip",
          "platforms": ["darwin"]
        },
        {
          "name": "@electron-forge/maker-deb",
          "platforms": ["linux"]
        }
      ]
    }
  },
  "scripts": {
    "start": "electron .",
    "package": "electron-forge package",
    "make": "electron-forge make", // 打包命令
    // ... 其他脚本
  }
}

步骤 3:执行打包

运行 make 命令:

npm run make

打包过程可能需要几分钟,完成后,在你的项目根目录下会生成一个 out 文件夹。

out 文件夹结构:

out/
├── make/
│   ├── win32/  // Windows 平台的可执行文件和安装包
│   ├── darwin/ // macOS 平台的 .app 应用包
│   └── linux/  // Linux 平台的 .deb 安装包
└── ...

你可以将 make/win32 目录下的内容分享给 Windows 用户,他们就可以直接运行你的应用了。


学习资源与最佳实践

官方资源:

社区与教程:

最佳实践:

  1. 架构清晰:严格区分主进程和渲染进程的职责,主进程只负责管理窗口和系统交互,UI 和业务逻辑尽量放在渲染进程中。
  2. 安全第一
    • 始终使用 contextBridgepreload 脚本来暴露 API,不要在渲染进程中直接引入 Node.js 模块 (require('fs'))。
    • 对所有来自渲染进程的数据进行验证和清理,防止 XSS 攻击。
  3. 性能优化
    • 避免渲染进程阻塞:长时间运行的任务(如文件读写、网络请求)应该放在主进程中执行,或者使用 Worker 线程。
    • 按需加载:如果应用功能复杂,可以考虑使用多窗口,只在需要时创建窗口。
  4. 调试
    • 使用 mainWindow.webContents.openDevTools() 打开开发者工具,可以像调试网页一样调试渲染进程。
    • 使用 console.log 或更专业的调试工具(如 VS Code 的 Debug 功能)来调试主进程。
分享:
扫描分享到社交APP
上一篇
下一篇