mcpField
D
desktop-framework-electron

desktop-framework-electron

github.com/agents-inc开发2656 次安装2 天前更新
代码仓库

关于 desktop-framework-electron

面向 Electron 桌面应用开发的技能指南,涵盖主进程与渲染进程架构、安全 IPC、原生系统 API 及打包更新实践。

主要功能

  1. 01主进程与渲染进程架构
  2. 02安全 BrowserWindow 配置
  3. 03通过 contextBridge 封装 IPC
  4. 04请求响应与消息推送模式
  5. 05原生系统 API 与深度链接
  6. 06应用打包及自动更新

适用场景

  1. 01搭建跨平台 Electron 桌面应用
  2. 02设计并验证进程间通信
  3. 03集成菜单、托盘和文件对话框
  4. 04配置分发及应用自动更新

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agents-inc/skills --skill desktop-framework-electron

安装后在 Claude Code 中输入/desktop-framework-electron确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

metadata.yaml
reference.md
examples/
core.md
ipc.md
native-apis.md
packaging.md
security.md

详细介绍

Electron 桌面应用

快速指南: Electron 应用运行两种进程:主进程(Node.js,管理窗口和系统 API)和渲染进程(Chromium,每个窗口一个)。它们之间的所有通信都通过 IPC 进行,并由预加载脚本使用 contextBridge 暴露精简、类型明确的 API。切勿禁用 contextIsolation。切勿在渲染进程中启用 nodeIntegration。使用 Electron Forge 或 Electron Builder 打包。通过 autoUpdater(macOS/Windows 上使用 Squirrel)或适用于所有平台的 electron-updater 自动更新。


<critical_requirements>

重要:使用此技能前

(必须保持 contextIsolation: true(默认设置)——禁用它会将整个预加载作用域暴露给不可信的渲染进程代码)

(必须在预加载脚本中使用 contextBridge.exposeInMainWorld()——切勿直接暴露 ipcRenderer)

(不得在任何 BrowserWindow 中启用 nodeIntegration: true——这会让渲染进程获得完整的 Node.js 访问权限,造成严重安全漏洞)

(必须在主进程中验证并清理通过 IPC 接收的所有数据——将渲染进程消息视为不可信输入)

(必须使用 ipcMain.handle() / ipcRenderer.invoke() 实现请求-响应式 IPC——避免使用会阻塞渲染进程的 sendSync)

(不得在启用 nodeIntegration 或禁用 contextIsolation 的情况下加载远程 URL——这相当于向远程站点授予完整的系统访问权限)

</critical_requirements>


自动检测: Electron、electron、BrowserWindow、ipcMain、ipcRenderer、contextBridge、preload、webPreferences、electron-builder、electron-forge、app.whenReady、electronAPI、mainWindow、autoUpdater、nativeTheme、safeStorage、Tray、Menu、dialog、protocol、shell

适用场景:

  • 构建跨平台桌面应用
  • 配置主进程 / 渲染进程架构
  • 设置安全的 IPC 通信模式
  • 集成原生操作系统功能(托盘、菜单、对话框、通知、文件系统)
  • 打包和分发桌面应用
  • 实现自动更新功能
  • 注册自定义协议处理程序 / 深层链接

不适用场景:

  • 为渲染进程选择 UI 框架(使用相应的 Web 框架技能)
  • 为渲染进程 UI 设置样式(使用相应的样式技能)
  • 与主进程无关的服务端或后端逻辑
  • 移动应用(Electron 仅适用于桌面)
  • 无需 GUI 的 CLI 工具

关键模式

模式 1:安全创建 BrowserWindow

每个 BrowserWindow 都必须使用预加载脚本,并采用安全默认设置:contextIsolation: true、sandbox: true、nodeIntegration: false。

const mainWindow = new BrowserWindow({
  width: 1200,
  height: 800,
  webPreferences: {
    preload: path.join(__dirname, "preload.js"),
    // contextIsolation: true  -- default since Electron 12
    // sandbox: true           -- default since Electron 20
    // nodeIntegration: false  -- default since Electron 5
  },
});

要点: 切勿覆盖安全默认设置。预加载脚本是主进程与渲染进程之间唯一的桥梁。参见 examples/core.md。


模式 2:使用 contextBridge 的预加载脚本

预加载脚本向渲染进程暴露范围精简、明确声明类型的 API。切勿直接暴露 ipcRenderer。

// preload.js
const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld("electronAPI", {
  readFile: (filePath) => ipcRenderer.invoke("read-file", filePath),
  onUpdateAvailable: (callback) => {
    ipcRenderer.on("update-available", (_event, data) => callback(data));
  },
});

要点: 每个暴露的方法都封装一个 IPC 通道。渲染进程调用 window.electronAPI.readFile(path),无需了解 IPC 内部细节。参见 examples/core.md。


模式 3:IPC 请求-响应(invoke/handle)

在主进程中使用 ipcMain.handle(),在预加载脚本中使用 ipcRenderer.invoke(),实现异步双向通信。

// main process
ipcMain.handle("read-file", async (_event, filePath) => {
  const content = await fs.readFile(filePath, "utf-8");
  return { success: true, content };
});

要点: handle/invoke 会返回 Promise。务必在处理程序中验证 filePath——切勿信任渲染进程的输入。所有 IPC 模式参见 examples/ipc.md。


模式 4:主进程向渲染进程发送消息

在主进程中使用 webContents.send(),并在预加载脚本中通过回调模式监听。

// main: send to specific window
mainWindow.webContents.send("update-progress", { percent: 45 });

// preload: expose listener
onUpdateProgress: (callback) => {
  ipcRenderer.on("update-progress", (_event, data) => callback(data));
},

要点: 渲染进程无法从主进程拉取消息——必须由主进程主动推送。监听器务必限定到特定通道。参见 examples/ipc.md。


模式 5:应用生命周期

主进程按照平台特定的惯例管理应用生命周期。

app.whenReady().then(() => {
  createWindow();
  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") app.quit();
});

**要点:**关闭所有窗口后,macOS 应用仍会保持运行(window-all-closed 不应退出应用)。点击程序坞图标时,activate 事件会重新创建窗口。请参阅 examples/core.md。


模式 6:原生操作系统集成

Electron 提供了用于对话框、菜单、托盘图标、通知等功能的原生 API,均通过主进程访问。

const { dialog } = require("electron");

const result = await dialog.showOpenDialog(mainWindow, {
  properties: ["openFile", "multiSelections"],
  filters: [{ name: "Documents", extensions: ["txt", "md", "json"] }],
});

**要点:**将 mainWindow 作为第一个参数传入时,原生对话框会以该窗口为模态窗口。请参阅 examples/native-apis.md。


模式 7:自定义协议 / 深度链接

注册应用以处理 myapp:// URL,从浏览器或其他应用进行深度链接。

if (process.defaultApp) {
  app.setAsDefaultProtocolClient("myapp", process.execPath, [
    path.resolve(process.argv[1]),
  ]);
} else {
  app.setAsDefaultProtocolClient("myapp");
}

**要点:**在开发环境中(process.defaultApp 为 true),必须将脚本路径作为参数传入。在 macOS 上,处理 app 对象上的 open-url 事件。在 Windows/Linux 上,通过 second-instance 事件处理。请参阅 examples/native-apis.md。


<decision_framework>

决策框架

IPC 模式选择
Which IPC pattern?
+-- Renderer needs a response from main?
|   +-- YES --> ipcMain.handle() + ipcRenderer.invoke()
+-- Renderer sends data, no response needed?
|   +-- YES --> ipcMain.on() + ipcRenderer.send()
+-- Main needs to push data to renderer?
|   +-- YES --> webContents.send() + ipcRenderer.on() (in preload)
+-- Two renderers need to communicate?
|   +-- YES --> Route through main process (never direct renderer-to-renderer)
+-- High-frequency data transfer (streaming)?
    +-- YES --> MessageChannelMain / MessagePort pair
窗口架构
How many windows?
+-- Single window app?
|   +-- One BrowserWindow, one preload script
+-- Multi-window (e.g., preferences, about)?
|   +-- Separate BrowserWindow per view, each with its own preload
+-- Frameless / custom title bar?
|   +-- frame: false + custom drag regions via CSS (-webkit-app-region: drag)
+-- Persistent background work?
    +-- Use a hidden BrowserWindow or utilityProcess (Electron 22+)

</decision_framework>


详细资源:


<red_flags>

严重问题

严重安全问题:

  • 禁用 contextIsolation(contextIsolation: false)——会将 preload 全局变量暴露给渲染进程
  • 启用 nodeIntegration: true ——会让渲染进程获得完整的 Node.js 访问权限(fs、child_process 等)
  • 通过 contextBridge 直接暴露 ipcRenderer,而不是封装各个通道
  • 未启用 sandbox: true 就加载远程/不受信任的 URL
  • 在生产环境中禁用 webSecurity(webSecurity: false 会禁用同源策略)
  • 未在主进程处理器中验证 IPC 参数(路径遍历、注入攻击)
  • 使用 shell.openExternal() 打开未经验证的 URL(可能执行任意命令)

架构问题:

  • 使用 ipcRenderer.sendSync() ——会阻塞渲染进程,导致界面卡顿
  • 将业务逻辑放在渲染进程中,而不是主进程中
  • 渲染进程之间直接通信(绕过主进程)
  • 使用 remote 模块(已在 Electron 14+ 中移除,存在安全和性能隐患)
  • 从渲染进程创建 BrowserWindow
  • 未按平台处理 window-all-closed(macOS 应用不应退出)

打包问题:

  • 在生产构建中包含 devDependencies(导致应用体积臃肿)
  • 未对应用进行代码签名(导致操作系统警告,并使 macOS 上的自动更新失败)
  • 打包 node_modules 时未进行精简或使用 ASAR 归档
  • 硬编码在开发环境和打包环境中各不相同的绝对路径
  • 在渲染进程代码中使用 __dirname(沙盒化的渲染进程中不可用)

常见错误:

  • 忘记调用 app.whenReady() ——ready 事件触发前 API 不可用
  • 未在 activate 事件中重新创建窗口(点击 macOS 程序坞图标无效果)
  • 在通过 <script> 标签加载的渲染进程脚本中使用 require()(沙盒化的渲染进程中不可用)
  • 对加载外部内容的 iframe 设置 nodeIntegrationInSubFrames: true
  • 未为渲染进程 HTML 设置适当的 Content-Security-Policy 标头

</red_flags>


<critical_reminders>

关键提醒

(你必须保持 contextIsolation: true(默认值)——禁用它会将整个 preload 作用域暴露给不可信的渲染器代码)

(你必须在 preload 脚本中使用 contextBridge.exposeInMainWorld()——绝不要直接暴露 ipcRenderer)

(你绝不能在任何 BrowserWindow 中启用 nodeIntegration: true——这会让渲染器获得完整的 Node.js 访问权限,造成严重的安全漏洞)

(你必须在主进程中验证并清理通过 IPC 接收的所有数据——将渲染器消息视为不可信输入)

(你必须使用 ipcMain.handle() / ipcRenderer.invoke() 实现请求-响应式 IPC——避免使用会阻塞渲染器的 sendSync)

不遵守这些规则会造成严重的安全漏洞,或导致桌面应用无法正常运行。

</critical_reminders>

评论

支持 Markdown