electron

Electron 入门与核心架构

By AI-Writer 8 min read

前言

Electron 是 GitHub 开源的桌面应用开发框架,2013 年以 atom-shell 之名诞生,2015 年更名为 Electron 并持续维护至今。它允许开发者使用 HTML、CSS、JavaScript 构建跨平台(Windows / macOS / Linux)桌面应用,著名的 VS Code、Slack、Postman、Figma 等产品均基于 Electron 开发。

Electron 的核心魅力在于:前端工程师无需学习 C++ 或 Swift,用熟悉的 Web 技术就能开发原生桌面应用。本文将深入剖析 Electron 的底层架构,并手把手搭建 Hello World 应用。

Electron 双引擎架构

Chromium + Node.js

Electron 实际上是一个「浏览器 + 服务器」的组合体:

plaintext
┌──────────────────────────────────────────────────────┐
│                    Electron 应用                       │
├─────────────────────────┬────────────────────────────┤
│       主进程 (Main)     │      渲染进程 (Renderer)     │
│   ┌─────────────────┐   │   ┌────────────────────┐  │
│   │  Node.js 运行时  │   │   │   Chromium 浏览器   │  │
│   │  (原生 API 访问) │   │   │  (HTML/CSS/JS 渲染) │  │
│   └─────────────────┘   │   └────────────────────┘  │
│         ↑               │            ↑               │
│    原生系统 API         │        DOM / CSS           │
└─────────────────────────┴────────────────────────────┘

主进程(Main Process)是整个应用的入口点,运行 Node.js 环境,拥有完整的系统级 API 访问权限。渲染进程(Renderer Process)是应用窗口内的页面,运行 Chromium 内核,负责 UI 渲染。

进程分工

职责主进程渲染进程
窗口管理创建销毁 BrowserWindow持有窗口实例
原生 APIdialog、Tray、Menu、App通过 IPC 调用主进程
文件系统完整 fs 读写权限受限(沙箱)
网络请求无限制受 CSP 限制
生命周期全应用唯一可多个(多窗口)

一个 Electron 应用只能有一个主进程,但可以有多个渲染进程(对应多个 BrowserWindow)。主进程崩溃会导致整个应用退出,而单个渲染进程崩溃只会影响对应窗口。

创建 Hello World 应用

环境要求

bash
# Node.js >= 18.0
node -v   # 建议使用 nvm 或 fnm 管理版本

# 包管理器(pnpm 推荐)
pnpm -v

手动搭建(不依赖脚手架)

bash
# 创建项目目录
mkdir electron-hello && cd electron-hello
pnpm init -y

# 安装 Electron(建议锁定版本)
pnpm add electron@35.2.0 -D

# 创建目录结构
mkdir -p src
javascript
// src/main.js  — 主进程入口
const { app, BrowserWindow } = require('electron');

app.whenReady().then(() => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    title: 'Hello Electron',
    webPreferences: {
      // 安全配置,后续文章详述
      nodeIntegration: false,
      contextIsolation: true,
    },
  });

  win.loadFile('index.html');
});

// 所有窗口关闭后退出(macOS 行为特殊处理)
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});
html
<!-- index.html — 渲染进程页面 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>Hello Electron</title>
  <style>
    body { font-family: sans-serif; display: flex; justify-content: center;
           align-items: center; height: 100vh; margin: 0; background: #f0f0f0; }
    h1 { color: #333; }
  </style>
</head>
<body>
  <h1>Hello, Electron!</h1>
  <p>你的第一个桌面应用正在运行。</p>
</body>
</html>
json
<!-- package.json -->
{
  "name": "electron-hello",
  "main": "src/main.js",
  "scripts": {
    "start": "electron .",
    "dev": "electron . --enable-logging"
  }
}
bash
# 启动应用
pnpm start

使用 Electron Forge 脚手架(推荐)

手动搭建适合学习,但生产项目推荐使用 Electron Forge:

bash
# 一键创建基于 Vite + TypeScript 的项目
pnpm create electron-app@latest my-app --template=vite-typescript

cd my-app
pnpm dev

Forge 会自动配置好 electron、构建工具、开发服务器,并生成规范的目录结构。

BrowserWindow 基础配置

BrowserWindow 是 Electron 中最核心的类,用于创建和管理应用窗口。以下是常用配置项:

javascript
const { BrowserWindow } = require('electron');

const mainWindow = new BrowserWindow({
  // 窗口尺寸
  width: 1200,
  height: 800,
  minWidth: 800,
  minHeight: 600,

  // 窗口标题
  title: 'My Electron App',

  // 是否显示窗口(用于后台任务)
  show: false,

  // 背景色
  backgroundColor: '#ffffff',

  // 是否使用系统边框窗口(false = 自定义标题栏)
  frame: true,

  // 透明窗口(需要 frame: false)
  transparent: false,

  // 窗口图标
  icon: './assets/icon.png',

  // Web 相关配置
  webPreferences: {
    nodeIntegration: false,
    contextIsolation: true,
    sandbox: true,
    preload: './preload.js',
  },
});

// 窗口准备好显示时再显示(避免白屏闪烁)
mainWindow.once('ready-to-show', () => {
  mainWindow.show();
});

// 加载页面
mainWindow.loadFile('index.html');
// 或加载远程 URL
// mainWindow.loadURL('https://example.com');

// 在 DevTools 中调试
mainWindow.webContents.openDevTools();

窗口事件

javascript
mainWindow.on('close', (e) => {
  // 阻止窗口关闭(例如:用户未保存时弹出确认)
  if (hasUnsavedChanges) {
    e.preventDefault();
    mainWindow.destroy(); // 强制关闭时用
  }
});

mainWindow.on('closed', () => {
  // 窗口已销毁,清除引用
  mainWindow = null;
});

mainWindow.on('maximize', () => console.log('窗口最大化'));
mainWindow.on('minimize', () => console.log('窗口最小化'));
mainWindow.on('unmaximize', () => console.log('窗口退出最大化'));

多窗口管理

Electron 支持创建多个窗口,适合邮件客户端(收件箱窗口 + 邮件详情窗口)等场景:

javascript
const { BrowserWindow } = require('electron');

// 主窗口
function createMainWindow() {
  const win = new BrowserWindow({ width: 1200, height: 800 });
  win.loadFile('main.html');
  return win;
}

// 详情窗口(子窗口)
function createDetailWindow(parent) {
  const child = new BrowserWindow({
    width: 600,
    height: 400,
    parent,          // 关联主窗口
    modal: true,     // 模态窗口(阻塞主窗口交互)
    show: false,
  });
  child.loadFile('detail.html');
  child.once('ready-to-show', () => child.show());
  return child;
}

进程间通信基础

Electron 的主进程与渲染进程默认完全隔离,不能直接相互调用。两者通过 IPC(Inter-Process Communication) 通信,这是 Electron 最核心的机制,后续文章将单独详述。

一个简单的点击计数器示例:

javascript
// main.js — 主进程
const { ipcMain } = require('electron');

ipcMain.handle('get-count', () => count);

ipcMain.handle('increment', () => {
  count += 1;
  return count;
});
javascript
// preload.js — 预加载脚本(后续详述)
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  getCount: () => ipcRenderer.invoke('get-count'),
  increment: () => ipcRenderer.invoke('increment'),
});
javascript
// index.html 中的渲染进程脚本
const btn = document.getElementById('counter');
btn.addEventListener('click', async () => {
  const count = await window.electronAPI.increment();
  btn.textContent = `点击次数: ${count}`;
});

小结

  • Electron = Chromium(渲染 UI)+ Node.js(系统级 API)
  • 主进程是应用入口,渲染进程负责页面展示,两者通过 IPC 通信
  • BrowserWindow 是创建窗口的核心类,支持丰富的配置选项
  • 生产项目推荐使用 Electron Forge 脚手架创建项目

下一篇文章我们将介绍 Electron Forge 开发环境配置,学习如何使用 Vite/Webpack 模板、热重载调试,以及 package.json 的关键字段含义。

#electron #入门 #架构 #进程

评论

A

Written by

AI-Writer

Related Articles

electron
#4

Preload 脚本与上下文隔离

理解 Preload 脚本的执行时机、contextBridge 安全暴露 API、nodeIntegration 与 contextIsolation 配置组合,以及主进程与渲染进程的安全边界

Read More
electron
#6

原生对话框与文件操作

使用 dialog.showOpenDialog、showSaveDialog、showMessageBox 原生对话框,Shell 模块打开外部链接和文件资源管理器,跨平台路径处理和用户数据目录访问

Read More