Skip to content
On this page

electron-toolkit

简介

electron-toolkit 是一个功能丰富的 Electron 开发工具集,它提供了三个主要模块:

  • @electron-toolkit/utils: 提供主进程工具函数,包括应用程序优化、窗口管理、平台检测等功能
  • @electron-toolkit/preload: 提供预加载脚本工具,简化渲染进程和主进程之间的通信
  • @electron-toolkit/typed-ipc: 提供类型安全的 IPC 通信工具,支持 TypeScript 类型检查和智能提示

@electron-toolkit/preload

安装

bash
pnpm add @electron-toolkit/preload

功能列表

IpcRenderer 相关

  • send: 发送消息到主进程(无响应)
  • sendTo: 发送消息到指定窗口
  • sendSync: 同步发送消息
  • sendToHost: 发送消息到嵌入的网页
  • invoke: 发送消息并等待响应
  • postMessage: 发送消息
  • on: 监听消息
  • once: 监听一次消息
  • removeAllListeners: 移除所有监听器
  • removeListener: 移除指定监听器

WebFrame 相关

  • insertCSS: 注入 CSS
  • setZoomFactor: 设置缩放比例
  • setZoomLevel: 设置缩放级别

WebUtils 相关

  • getPathForFile: 获取文件路径

NodeProcess 相关

  • platform: 平台信息
  • versions: 版本信息
  • env: 环境变量

使用示例

ts
import { contextBridge } from 'electron'
import { electronAPI, exposeElectronAPI } from '@electron-toolkit/preload'

// 方法一:使用 contextBridge 手动暴露 API(推荐在 TypeScript 项目中使用)
if (process.contextIsolated) {
  try {
    contextBridge.exposeInMainWorld('electron', electronAPI)
  } catch (error) {
    console.error(error)
  }
} else {
  window.electron = electronAPI
}

// 方法二:使用封装好的函数自动暴露 API
// exposeElectronAPI()

// 类型定义(在 .d.ts 文件中)
import { ElectronAPI } from '@electron-toolkit/preload'

declare global {
  interface Window {
    electron: ElectronAPI
  }
}

// 使用示例
contextBridge.exposeInMainWorld('api', {
  /**
   * 发送消息到主进程(无响应)
   */
  sayHello: () => window.electron.ipcRenderer.send('electron:say', 'hello'),

  /**
   * 发送消息到主进程并等待响应
   * @returns {Promise<unknown>} 主进程返回的数据
   */
  doSomething: () => window.electron.ipcRenderer.invoke('electron:doAThing', ''),

  /**
   * 监听主进程消息
   * @returns {() => void} 移除监听器的函数
   */
  onReply: (callback: (event: unknown, args: unknown) => void) => {
    const removeListener = window.electron.ipcRenderer.on('electron:reply', callback)
    return removeListener
  },
})

@electron-toolkit/utils

安装

bash
pnpm add @electron-toolkit/utils

功能列表

electronApp

  • setAppUserModelId: 设置应用程序 ID,用于 Windows 通知和任务栏分组(仅 Windows 平台)
  • setAutoLaunch: 设置应用程序是否开机自启动(支持 Windows 和 macOS 平台)
  • skipProxy: 跳过系统代理设置

optimizer

  • watchWindowShortcuts: 监听窗口基础操作快捷键(最小化、最大化、关闭等)
  • registerShortcuts: 注册自定义全局快捷键
  • registerFramelessWindowIpc: 注册无边框窗口 IPC 通信

platform

  • is.dev: 检查是否为开发环境
  • is.mac: 检查是否为 macOS 系统
  • is.linux: 检查是否为 Linux 系统
  • is.windows: 检查是否为 Windows 系统

Storage

  • get: 读取配置
  • set: 保存配置
  • clearInvalidConfig: 清理无效配置

@electron-toolkit/typed-ipc

安装

bash
pnpm add @electron-toolkit/preload @electron-toolkit/typed-ipc

功能特点

  • 提供类型安全的 IPC 通信
  • 支持主进程和渲染进程的类型检查和智能提示
  • 支持监听器参数、处理器参数和返回值类型的检查
  • 保持原有的 IPC 编写方式,易于理解和维护

使用示例

1. 使用 @electron-toolkit/preload 暴露 Electron API

ts
import { contextBridge } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'

// 方法一:手动暴露 API
if (process.contextIsolated) {
  try {
    contextBridge.exposeInMainWorld('electron', electronAPI)
  } catch (error) {
    console.error(error)
  }
} else {
  window.electron = electronAPI
}

// 方法二:使用封装好的函数
import { exposeElectronAPI } from '@electron-toolkit/preload'
exposeElectronAPI()

2. 定义 IPC 事件类型

ts
// 主进程 IPC 事件类型
type IpcEvents =
  | {
      ping: [string] // 监听器事件映射
    }
  | {
      'say-hello': () => string // 处理器事件映射
    }

// 渲染进程 IPC 事件类型
type IpcRendererEvent = {
  ready: [boolean]
}

3. 主进程中注册监听器和处理器

ts
import { IpcListener, IpcEmitter } from '@electron-toolkit/typed-ipc/main'

// 创建监听器和发射器实例
const ipc = new IpcListener<IpcEvents>()
const emitter = new IpcEmitter<IpcRendererEvent>()

// 监听事件
ipc.on('ping', (e, arg) => {
  console.log(arg) // arg 的类型为 string
  emitter.send(e.sender, 'ready', true)
})

// 注册处理器
ipc.handle('say-hello', () => {
  return 'hello' // 返回值类型必须为 string
})

4. 渲染进程中发送和接收消息

ts
import { IpcListener, IpcEmitter } from '@electron-toolkit/typed-ipc/renderer'

// 创建监听器和发射器实例
const ipc = new IpcListener<IpcRendererEvent>()
const emitter = new IpcEmitter<IpcEvents>()

// 监听主进程消息
ipc.on('ready', (e, arg) => {
  console.log(arg) // arg 的类型为 boolean
})

// 发送消息到主进程
emitter.send('ping', 'pong')

// 调用主进程处理器
emitter.invoke('say-hello').then((str) => {
  console.log(str) // str 的类型为 string
})

@electron-toolkit/utils 使用示例

应用程序配置

ts
import { app, BrowserWindow } from 'electron'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'

app.whenReady().then(() => {
  /**
   * 初始化应用程序
   * 设置应用程序 ID,用于 Windows 通知和任务栏分组
   */
  electronApp.setAppUserModelId('com.example')

  /**
   * 设置开机自启动
   * @param {boolean} auto - 是否开机自启动
   */
  electronApp.setAutoLaunch(true)

  /**
   * 跳过系统代理设置
   * 用于解决某些网络环境下的连接问题
   */
  await electronApp.skipProxy()

  // 创建主窗口
  const mainWindow = new BrowserWindow({
    width: 900,
    height: 670,
    show: false, // 初始化完成前隐藏窗口
    autoHideMenuBar: true, // 自动隐藏菜单栏
    webPreferences: {
      preload: path.join(__dirname, '../preload/index.js'),
      sandbox: false,
      contextIsolation: true,
      nodeIntegration: false,
    },
  })

  /**
   * 窗口优化配置
   */
  // 注册窗口基础快捷键(最小化、最大化、关闭等)
  optimizer.watchWindowShortcuts(mainWindow)

  // 注册无边框窗口 IPC 通信
  optimizer.registerFramelessWindowIpc()
  // 注册以下事件:
  // - win:invoke show: 显示窗口
  // - win:invoke showInactive: 显示窗口但不聚焦
  // - win:invoke min: 最小化窗口
  // - win:invoke max: 最大化窗口
  // - win:invoke close: 关闭窗口

  // 注册自定义全局快捷键
  optimizer.registerShortcuts({
    // 打开开发者工具
    'CommandOrControl+Shift+I': (win: BrowserWindow) => {
      win.webContents.toggleDevTools()
    },
    // 刷新页面
    'CommandOrControl+R': (win: BrowserWindow) => {
      win.webContents.reload()
    },
  })

  /**
   * 环境检测示例
   */
  // 开发环境检测
  if (is.dev) {
    mainWindow.webContents.openDevTools()
  }

  // 操作系统检测
  if (is.mac) {
    app.dock.setIcon('/path/to/icon.png')
  } else if (is.linux) {
    // Linux 特定配置
  } else if (is.windows) {
    // Windows 特定配置
  }

  /**
   * 本地存储示例
   */
  const storage = new Storage({
    fileName: 'config', // 存储文件名
    clearInvalidConfig: true, // 自动清理无效配置
  })

  // 读取配置
  const config = storage.get('someKey')

  // 保存配置
  storage.set('someKey', { value: 'example' })
})

@electron-toolkit/preload 使用示例

ts
import { contextBridge } from 'electron'
import { electronAPI, exposeElectronAPI } from '@electron-toolkit/preload'

// 方法一:使用 contextBridge 手动暴露 API(推荐在 TypeScript 项目中使用)
if (process.contextIsolated) {
  try {
    contextBridge.exposeInMainWorld('electron', electronAPI)
  } catch (error) {
    console.error(error)
  }
} else {
  window.electron = electronAPI
}

// 方法二:使用封装好的函数自动暴露 API
// exposeElectronAPI()

// 类型定义(在 .d.ts 文件中)
import { ElectronAPI } from '@electron-toolkit/preload'

declare global {
  interface Window {
    electron: ElectronAPI
  }
}

// 可用的 API
// IpcRenderer
// - send: 发送消息到主进程(无响应)
// - sendTo: 发送消息到指定窗口
// - sendSync: 同步发送消息
// - sendToHost: 发送消息到嵌入的网页
// - invoke: 发送消息并等待响应
// - postMessage: 发送消息
// - on: 监听消息
// - once: 监听一次消息
// - removeAllListeners: 移除所有监听器
// - removeListener: 移除指定监听器

// WebFrame
// - insertCSS: 注入 CSS
// - setZoomFactor: 设置缩放比例
// - setZoomLevel: 设置缩放级别

// WebUtils
// - getPathForFile: 获取文件路径

// NodeProcess
// - platform: 平台信息
// - versions: 版本信息
// - env: 环境变量

// 使用示例
contextBridge.exposeInMainWorld('api', {
  /**
   * 发送消息到主进程(无响应)
   */
  sayHello: () => window.electron.ipcRenderer.send('electron:say', 'hello'),

  /**
   * 发送消息到主进程并等待响应
   * @returns {Promise<unknown>} 主进程返回的数据
   */
  doSomething: () => window.electron.ipcRenderer.invoke('electron:doAThing', ''),

  /**
   * 监听主进程消息
   * @returns {() => void} 移除监听器的函数
   */
  onReply: (callback: (event: unknown, args: unknown) => void) => {
    const removeListener = window.electron.ipcRenderer.on('electron:reply', callback)
    return removeListener
  },
})

高级功能

开发环境检测

ts
import { is } from '@electron-toolkit/utils'

// is.dev: 检查是否为开发环境
if (is.dev) {
  mainWindow.webContents.openDevTools()
}

// is.mac: 检查是否为 macOS 系统
if (is.mac) {
  app.dock.setIcon('/path/to/icon.png')
}

// is.linux: 检查是否为 Linux 系统
if (is.linux) {
  // Linux 特定配置
}

// is.windows: 检查是否为 Windows 系统
if (is.windows) {
  // Windows 特定配置
}

应用程序优化

ts
import { BrowserWindow, app } from 'electron'
import { electronApp, optimizer, platform, Storage } from '@electron-toolkit/utils'

// 应用程序配置
electronApp.setAppUserModelId('com.example') // 设置应用程序 ID
electronApp.disableHardwareAcceleration() // 禁用硬件加速,解决某些显卡兼容性问题

optimizer.registerFramelessWindowIpc() // 注册无边框窗口 IPC 通信
//帮你注册以下事件
// ipcRenderer.send('win:invoke', 'show')
// ipcRenderer.send('win:invoke', 'showInactive')
// ipcRenderer.send('win:invoke', 'min')
// ipcRenderer.send('win:invoke', 'max')
// ipcRenderer.send('win:invoke', 'close')

// 注册自定义全局快捷键
// 注意:这个方法用于注册特定功能的自定义快捷键
// 与 watchWindowShortcuts 不同,registerShortcuts 允许你定义任意快捷键组合和对应的处理函数
optimizer.registerShortcuts({
  // 打开开发者工具快捷键
  'CommandOrControl+Shift+I': (win: BrowserWindow) => {
    win.webContents.toggleDevTools()
  },
  // 刷新页面快捷键
  'CommandOrControl+R': (win: BrowserWindow) => {
    win.webContents.reload()
  },
  // 你可以添加更多自定义快捷键...
})

// 本地存储配置
const storage = new Storage({
  fileName: 'config', // 存储文件名
  clearInvalidConfig: true, // 自动清理无效配置
})

// 读取配置
const config = storage.get('someKey')

// 保存配置
storage.set('someKey', { value: 'example' })

窗口管理

ts
/**
 * 创建应用程序主窗口
 * @returns {BrowserWindow} 返回创建的窗口实例
 */
const createWindow = () => {
  const mainWindow = new BrowserWindow({
    width: 900,
    height: 670,
    show: false, // 初始化完成前隐藏窗口
    autoHideMenuBar: true, // 自动隐藏菜单栏
    webPreferences: {
      preload: path.join(__dirname, '../preload/index.js'),
      sandbox: false,
      nodeIntegration: true,
      contextIsolation: true,
    },
  })

  // 窗口优化配置
  //用于监听窗口默认快捷键
  optimizer.watchWindowShortcuts(mainWindow) // 注册窗口快捷键
  // 并在渲染进程中使用 IPC 消息控制窗口

  // 根据环境加载不同内容
  if (is.dev && process.env.ELECTRON_RENDERER_URL) {
    mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL)
    mainWindow.webContents.openDevTools()
  } else {
    mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'))
  }

  // 优化窗口显示
  mainWindow.on('ready-to-show', () => {
    mainWindow.show() // 初始化完成后显示窗口
  })

  return mainWindow
}

要保持清醒 永远不抱有意外的幻想 凭空的期待最要命