Utility Process Topologies
Electron’s utility process runs in a separate Node.js thread. You can connect it via MessagePort for offloading heavy computation.
Utility Worker
Section titled “Utility Worker”// utility-process.ts (runs in a utility process)import { createParentPortHandler } from 'electron-messageport-trpc/utility';import { utilityRouter } from './router';
createParentPortHandler({ router: utilityRouter, parentPort: process.parentPort,});Main to Utility
Section titled “Main to Utility”// main processimport { createTRPCClient } from '@trpc/client';import { MessageChannelMain, utilityProcess } from 'electron';import { mainPortLink } from 'electron-messageport-trpc/main';
const child = utilityProcess.fork('utility-process.js');const { port1, port2 } = new MessageChannelMain();
child.postMessage({ type: 'connect' }, [port1]);
const client = createTRPCClient({ links: [mainPortLink({ port: port2 })],});Renderer to Utility
Section titled “Renderer to Utility”// main process brokerimport { createPortBroker } from 'electron-messageport-trpc/main';import { utilityProcess } from 'electron';
const child = utilityProcess.fork('utility-process.js');const broker = createPortBroker();
win.webContents.on('did-finish-load', () => { const { serverPort } = broker.createRendererPort(win.webContents); child.postMessage({ type: 'connect' }, [serverPort]);});This keeps the main process out of the request path. It only creates and transfers the port pair.
Architecture
Section titled “Architecture”Renderer <== MessagePort ==> Main Process <== parentPort ==> Utility ProcessChoosing a Topology
Section titled “Choosing a Topology”| Topology | Use Case | Pros | Cons |
|---|---|---|---|
| Renderer to Main | Standard RPC, DB access, native APIs | Simple setup | Main process is the bottleneck |
| Main to Utility | Heavy computation, background tasks | Offloads main thread | Extra process overhead |
| Renderer to Utility | Direct offloading via broker | Keeps main out of the request path | Most complex setup |