Migrate from Manual IPC
This guide shows how to move from manual ipcMain + custom preload wiring to controller-based IPC with generated renderer types.
Migration goals
- Replace stringly-typed channels with controller methods
- Remove duplicated preload wiring
- Centralize API shape in main-process controller signatures
Step 1: Replace manual handlers with controller methods
Before:
ipcMain.handle("users.get_profile", async (_event, userId: string) => {
return userService.getProfile(userId);
});
After:
@IpcController("users")
class UsersController {
@IpcHandle("getProfile")
async getProfile(userId: string) {
return userService.getProfile(userId);
}
}
Step 2: Register controllers at startup
createIpcApp({
controllers: [UsersController],
resolver: {
resolve: (Controller) => new Controller(),
},
});
If you already use DI, adapt resolve to your container.
Step 3: Replace manual preload bridge with setupPreload
Before:
contextBridge.exposeInMainWorld("api", {
getProfile: (id: string) => ipcRenderer.invoke("users.get_profile", id),
});
(Using Electron's contextBridge and ipcRenderer.)
After:
import { setupPreload } from "@electron-ipc-bridge/core/preload";
void setupPreload(); // exposes window.ipc by default
Step 4: Update renderer calls
Before:
const profile = await window.api.getProfile(userId);
After:
const profile = await window.ipc.users.getProfile(userId);
Step 5: Validate behaviour and remove legacy code
- Remove old
ipcMain.handle/ipcMain.onregistrations for migrated endpoints - Remove redundant preload bridge methods that are now generated
- Keep reflect-metadata import at main entrypoint
- Confirm renderer compiles against generated API types
Common migration pitfalls
- Namespace collisions across controllers
- Missing decorator/metadata TypeScript config
- Preload path mismatch in packaged builds
- Dynamic controller registration patterns that break plugin analysis
Suggested incremental rollout
- Migrate one domain controller (for example,
users) - Keep legacy channels for untouched domains
- Verify behaviour and typing in renderer
- Migrate remaining domains and remove legacy bridge