Agent Skillslichtblick-suite/lichtblick › electron-internals

electron-internals

GitHub

提供Electron内部机制知识,涵盖主/渲染进程通信、contextBridge模式、BrowserWindow生命周期及原生菜单集成。强调安全规范,如隔离Node访问、禁止直接暴露ipcRenderer,并解析多桥接架构与窗口管理实现细节。

.github/skills/electron-internals/SKILL.md lichtblick-suite/lichtblick

Trigger Scenarios

询问Electron进程架构 配置contextBridge或preload脚本 处理BrowserWindow生命周期 集成原生菜单系统 解决Electron安全限制问题

Install

npx skills add lichtblick-suite/lichtblick --skill electron-internals -g -y
More Options

Non-standard path

npx skills add https://github.com/lichtblick-suite/lichtblick/tree/develop/.github/skills/electron-internals -g -y

Use without installing

npx skills use lichtblick-suite/lichtblick@electron-internals

指定 Agent (Claude Code)

npx skills add lichtblick-suite/lichtblick --skill electron-internals -a claude-code -g -y

安装 repo 全部 skill

npx skills add lichtblick-suite/lichtblick --all -g -y

预览 repo 内 skill

npx skills add lichtblick-suite/lichtblick --list

SKILL.md

Frontmatter
{
    "name": "electron-internals",
    "description": "Deep Electron implementation knowledge: main\/renderer process communication, contextBridge patterns, BrowserWindow lifecycle, native menu integration, and security considerations."
}

Electron Internals Skill

Process Architecture

Main Process

  • Node.js environment with full OS access
  • Manages BrowserWindow instances
  • Handles app lifecycle (startup, quit, focus)
  • Single-instance lock prevents multiple app copies

Preload Script

  • Runs in renderer context BUT with Node.js access
  • Bridge between main and renderer via contextBridge.exposeInMainWorld()
  • Must be minimal — every import adds to startup time

Renderer Process

  • Standard web environment (Chromium)
  • No direct Node.js access (security)
  • Communicates with main via exposed bridges

contextBridge Pattern

The preload script (packages/suite-desktop/src/preload/index.ts) exposes four separate bridges to the renderer — not a single desktopBridge:

// packages/suite-desktop/src/preload/index.ts
contextBridge.exposeInMainWorld("ctxbridge", ctx);            // main app/context API (Desktop)
contextBridge.exposeInMainWorld("menuBridge", menuBridge);    // native menu event subscription
contextBridge.exposeInMainWorld("storageBridge", storageBridge); // local file storage CRUD
contextBridge.exposeInMainWorld("desktopBridge", desktopBridge); // desktop-specific operations
Bridge Type Purpose
ctxbridge Desktop Core context API consumed by the renderer app shell
menuBridge NativeMenuBridge Subscribe to forwarded native menu events (addIpcEventListener)
storageBridge Storage Local file storage: list, all, get, put, delete
desktopBridge Desktop Desktop-specific operations (deep links, color scheme, etc.)
// renderer — consuming a bridge
const desktopBridge = (global as { desktopBridge: Desktop }).desktopBridge;
const storageBridge = (global as { storageBridge: Storage }).storageBridge;
await storageBridge.list("layouts");

Security Rules

  • Never expose ipcRenderer directly
  • Class instances do not survive the bridge — only plain functions/objects are exposed (prototypes are lost), which is why storage methods are .bind()-attached in preload
  • Each bridge method is a typed, scoped function
  • No eval(), no remote module usage
  • CSP headers prevent inline scripts

BrowserWindow Management (StudioWindow)

class StudioWindow {
  #window: BrowserWindow;

  constructor() {
    this.#window = new BrowserWindow({
      webPreferences: {
        preload: path.join(__dirname, "preload.js"),
        contextIsolation: true,
        nodeIntegration: false,
        sandbox: false,  // needed for preload Node access
      },
    });
  }
}

Window Lifecycle

  1. App starts → StudioWindow created
  2. Preload runs → bridges exposed
  3. Renderer loads → React app mounts
  4. Deep links → forwarded to renderer via bridge
  5. Close → cleanup, save state, quit

Native Menu Integration

// Main process builds menu template
const template: MenuItemConstructorOptions[] = [
  { label: "File", submenu: [
    { label: "Open File...", click: () => sendToRenderer("open-file") },
  ]},
];

// Renderer receives via menuBridge
menuBridge.on("menu-event", (event: ForwardedMenuEvent) => {
  switch (event) {
    case "open-file": // show file picker
  }
});

File System Access

Layout / Storage Loading

  • Local storage entries are read/written via storageBridge (list, all, get, put, delete)
  • The renderer's DesktopLayoutLoader (packages/suite-desktop/src/renderer/services/DesktopLayoutLoader.ts) wraps these calls

Extension Loading

  • .foxe files in extension directory
  • DesktopExtensionLoader (filesystem type) reads directly via bridge
  • Supports install/uninstall by copying/deleting files

Deep Links

lichtblick://open?url=https://example.com/recording.mcap
  • OS protocol registration uses the legacy foxglove scheme: app.setAsDefaultProtocolClient("foxglove") (packages/suite-desktop/src/main/index.ts)
  • Handled deep-link URLs use the lichtblick:// scheme — the open-url handler and second-instance argv filter both match arg.startsWith("lichtblick://")
  • Recognized links include lichtblick://open?... and lichtblick://signin-complete
  • Second-instance handler re-emits open-url and forwards to the existing window
  • Parsed in renderer to open the appropriate data source

⚠️ The protocol-client registration argument ("foxglove") differs from the URL scheme the app actually parses (lichtblick://). Do not assume they are the same string.

Build & Packaging

  • desktop/electronBuilderConfig.js — electron-builder configuration
  • desktop/webpack.config.ts — webpack for main/preload/renderer
  • Output: .dmg (macOS), .exe/.msi (Windows), .deb/.AppImage (Linux)
  • Auto-update via electron-updater (if configured)

Performance Tips

  1. Preload weight: Keep preload imports minimal — delays window show
  2. IPC serialization: Large objects are serialized — prefer transferring file paths over file contents
  3. Window show: Use show: false + ready-to-show event for smooth startup
  4. Background throttling: Electron throttles background tabs by default — respect this for power usage

Version History

  • cab9317 Current 2026-07-24 12:16

Same Skill Collection

.github/skills/3d-rendering/SKILL.md
.github/skills/caching-internals/SKILL.md
.github/skills/deserialization/SKILL.md
.github/skills/e2e-playwright-mcp/SKILL.md
.github/skills/extensions-internals/SKILL.md
.github/skills/layouts-internals/SKILL.md
.github/skills/mcap-format/SKILL.md
.github/skills/message-path/SKILL.md
.github/skills/message-pipeline/SKILL.md
.github/skills/panel-extension-api/SKILL.md
.github/skills/panel-image/SKILL.md
.github/skills/panel-log/SKILL.md
.github/skills/panel-map/SKILL.md
.github/skills/panel-raw-messages/SKILL.md
.github/skills/panel-state-transitions/SKILL.md
.github/skills/panel-user-scripts/SKILL.md
.github/skills/performance/SKILL.md
.github/skills/player-internals/SKILL.md
.github/skills/plot-internals/SKILL.md
.github/skills/remote-caching/SKILL.md
.github/skills/test-conventions/SKILL.md
.github/skills/theme/SKILL.md
.github/skills/unit-testing/SKILL.md
.github/skills/web-workers/SKILL.md
.github/skills/websocket-connection/SKILL.md

Metadata

Files
0
Version
cab9317
Hash
0a69c052
Indexed
2026-07-24 12:16

trang chủ - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-08 06:17
浙ICP备14020137号-1 $bản đồ khách truy cập$