Skip to content

TypeScript RPC library for Electron that supports transporting callbacks or objects.

License

Notifications You must be signed in to change notification settings

mukea-org/electron-callback-rpc

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

31 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

electron-callback-rpc

δΈ­ζ–‡

  • A lightweight RPC library built for Electron (Main ↔ Renderer), supporting Cross-Process Callbacks and Complex Type Transmission.

⚠️ Pre-Release Notice

Current version < 1.0.0. The project is in the early stages of development. Portions of this code were generated with AI assistance. While all code has undergone manual review and validation via unit tests, unknown edge cases or instabilities may still exist. Prior to the v1.0.0 release, the API is subject to Breaking Changes at any time. Please use with caution in production environments and pin specific versions.

Core features focus on:

  1. Promise-based Service Calls: The Renderer calls Main process methods as native asynchronous functions, providing a seamless local-call experience.
  2. Cross-process Callback Support: Functions and objects with methods can be passed as arguments or return values across processes, enabling true bidirectional interaction.
  3. Rich Type Preservation: Supports native types like Map, Set, Date, Error, BigInt, and Buffer, avoiding data distortion caused by the "Forced JSONification" typical in IPC communication.

Requirement: electron >= 13.0.0


πŸ“– Background & Motivation

This project is a fork of @ggworks/electron-rpc. While the original library established an excellent IPC method invocation model, complex real-world business scenarios often require greater flexibility:

  • Callbacks as First-Class Citizens: We need to transmit not just data, but capabilities. This includes passing callback functions to the main process to report progress or handle asynchronous results.
  • High-Fidelity Types: Electron IPC natively supports the Structured Clone algorithm. We fully leverage this to avoid unnecessary serialization overhead and type loss.
  • Controllable Lifecycle: For cross-process references, we emphasize an explicit resource release (Dispose) mechanism, complemented by an internal automatic garbage collection strategy to minimize the risk of memory leaks.

Core Differences from @ggworks/electron-rpc

  • Focused: Exclusively focuses on the Request/Response + Callback model.
  • Streamlined: Removed the event subscription model (no on/once/off semantics; explicit business-level callbacks are recommended instead).
  • Enhanced: Strengthened the ability to pass cross-process objects/functions and improved support for non-standard JSON types.

🧩 API Overview

Main Process

const server = new Server() // Create RPC Server
const service = createRpcService(instance) // Wrap object / instance
server.registerService('namespace', service) // Register service

Renderer Process

const client = new Client(ipcRenderer) // Create Client
const proxy = createProxyService(client, 'namespace') // Create typed proxy

// Invoke
proxy.methodName(args)

πŸ“¦ Installation

npm i @mukea/electron-callback-rpc

πŸš€ Quick Start

1. Define Type Interface (Shared)

It is recommended to define interfaces in a shared file to enable full TypeScript type inference.

export interface IDemoService {
  echo(text: string): Promise<string>
  run(taskName: string, onProgress: (percent: number) => void): Promise<string>
}

2. Main Process: Implement and Register

import { Server, createRpcService } from '@mukea/electron-callback-rpc'

class DemoService implements IDemoService {
  async echo(text: string) {
    return text
  }

  async run(taskName: string, onProgress: (percent: number) => void) {
    onProgress(0)
    onProgress(50)
    onProgress(100)
    return `done:${taskName}`
  }
}

const server = new Server()
// Wrap the instance as an RPC service and register it
server.registerService('demo', createRpcService(new DemoService()))

3. Renderer Process: Create Proxy and Call

import { Client, createProxyService } from '@mukea/electron-callback-rpc'

// Initialize client (requires ipcRenderer)
const client = new Client(window.ipcRenderer)
const demo = createProxyService<IDemoService>(client, 'demo')

// Scenario 1: Standard async call
const echoed = await demo.echo('hello')
console.log(echoed)

// Scenario 2: Call with callback
const result = await demo.run('build', (percent) => {
  console.log('Build progress:', percent)
})
console.log(result)

⚠️ TypeScript Configuration Note

This library uses exports to distinguish between the Main process (CJS) and the Renderer process (ESM). If you encounter type inference errors in the Renderer process (e.g., VSCode pointing to the wrong dist/main path), ensure your Renderer's tsconfig.json is configured with a modern module resolution strategy:

// tsconfig.json (Renderer Process)
{
  "compilerOptions": {
    // Adapt for modern bundlers like Vite/Webpack (requires TS 5.0+)
    "moduleResolution": "bundler",
    // Explicitly specify browser environment to force hitting the "browser" condition in exports
    "customConditions": ["browser"] 
  }
}

Benchmarks

We conducted comprehensive performance benchmarking of electron-callback-rpc against native Electron IPC, covering throughput, latency, serialization, error handling, and memory usage.

This document cites a subset of the data. You can run the electron project within the example directory to generate full results.

Test Environment

  • Platform: arm64 Darwin 25.1.0 / Apple M4
  • Node.js: v24.11.0
  • Electron: v39.2.7

Results

Throughput Comparison
Throughput Comparison
Latency Comparison
Latency Comparison
Serialization Performance
Serialization Performance
Error Handling Performance
Error Handling Performance
Memory Usage
Memory Usage

πŸš€ Throughput (Operations/sec)

Test Scenario RPC Package Native IPC Performance Ratio
Batch Add (15,000 ops) 5,500 ops/sec 8,081 ops/sec 0.68x
Batch Process (6,000 ops) 15,476 ops/sec 15,940 ops/sec 0.97x
  • Average Latency: RPC 0.12ms vs Native 0.09ms (+33.3% overhead)
  • Overall Throughput: RPC maintains 87-97% of native performance in high-frequency call scenarios.

πŸ“Š Serialization Performance

Data Type RPC Package Native IPC Performance Ratio
Simple Object (5,000 ops) 22,222 ops/sec 19,747 ops/sec 1.13x
Complex Object (2,500 ops) 15,509 ops/sec 17,643 ops/sec 0.88x
  • Average Latency: RPC 0.10ms vs Native 0.09ms (+11.1% overhead)
  • Serialization Advantage: For simple object handling, RPC is 13% faster than native IPC.

⚑ Latency (Round-trip time)

Operation Type RPC Package Native IPC Latency Overhead
No-op (5,000 ops) 0.041ms 0.046ms 0.0%
Small Data Echo (5,000 ops) 0.042ms 0.042ms 0.0%
  • Ultra-low Latency: In lightweight operations, RPC latency is virtually identical to native IPC.
  • Throughput: 21,471 ops/sec vs 21,060 ops/sec (1.02x).

πŸ›‘οΈ Error Handling Performance

Scenario RPC Package Native IPC Performance Ratio
Success Path (5,000 ops) 22,036 ops/sec 23,753 ops/sec 0.93x
Error Path (5,000 ops) 14,472 ops/sec 11,593 ops/sec 1.25x
  • Error Handling Advantage: RPC is 25% faster than native IPC in error scenarios due to optimized exception propagation.
  • Average Latency: Virtually identical for both (0.06ms).

πŸ’Ύ Memory Usage

Test Scenario RPC Package Native IPC Performance Ratio
Large Array (30 ops) 36 ops/sec 38 ops/sec 0.95x
1MB Buffer (60 ops) 632 ops/sec 628 ops/sec 1.01x
  • Large Data Processing: Performance loss is controlled within 5% when handling large data structures.
  • Memory Efficiency: Slightly outperforms native IPC in 1MB buffer operations.

Key Conclusions

  1. Extremely Low Latency: In no-op and small data echo scenarios, the library's latency is on par with native IPC (~0.04ms), making the absolute overhead negligible.
  2. Superior Error Handling: Thanks to optimized exception propagation mechanisms, error path processing is 25% faster than native.
  3. Serialization Performance: Simple object transmission is 13% faster than native; complex objects show only ~12% performance loss.
  4. Throughput: In high-frequency call scenarios, it maintains 87%-97% of native IPC throughput.

Summary: While providing powerful type safety and callback capabilities, electron-callback-rpc introduces no significant performance bottlenecks and even outperforms native implementation in specific scenarios (e.g., error handling, simple objects).


⚠️ Best Practices

  • Process Model: This library is designed for the real multi-process Electron environment.
  • Event Subscription: We do not provide EventEmitter style APIs. If you need to push events, please explicitly design subscribe(callback) methods in your business interface.
  • Resource Management: Although the library includes an internal garbage collection mechanism, for long-lifecycle callbacks or objects, it is recommended to explicitly provide dispose() or unsubscribe() methods in your interface to ensure absolute safety.

License

MIT

About

TypeScript RPC library for Electron that supports transporting callbacks or objects.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 48.4%
  • Vue 47.9%
  • CSS 2.7%
  • Other 1.0%