Install & rebuild
$ npm install serialpilot @serialpilot/bindings-cpp
$ npm install --save-dev electron-rebuild
$ npx electron-rebuild
electron-rebuild compiles the native binding against the V8 ABI shipped with your installed Electron version. Run it after every Electron upgrade.
Rule #1 — main process only
Create SerialPilot instances in the main process. Don't reach for them from a renderer; you'll fight context isolation and lose.
// main.js const { SerialPilot } = require('serialpilot') const { ipcMain } = require('electron')
ipcMain.handle(‘list-ports’, () => SerialPilot.list())
Rule #2 — bridge through contextBridge
Expose a small, audited surface to the renderer with contextBridge. Never set nodeIntegration: true:
// preload.js const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(‘serialpilot’, { listPorts: () => ipcRenderer.invoke(‘list-ports’), open: (opts) => ipcRenderer.invoke(‘open-port’, opts), write: (id, data) => ipcRenderer.invoke(‘port-write’, id, data), })
Packaging gotchas
| Tool | What to do |
|---|---|
electron-builder | Set "npmRebuild": true in build; it rebuilds natives for the target Electron during the packaging step. |
electron-forge | Add @electron/rebuild as a maker plugin so each build picks up native changes. |
- ASAR: exclude
@serialpilot/bindings-cppfrom the asar bundle (Node can'trequire()a.nodefile from inside an asar archive). - Signing on macOS: the
.nodebinary needs thecom.apple.security.cs.allow-jitentitlement — most Electron projects already include this. - Linux distribution: remind users to add themselves to
dialoutat first run, or your app getsPermissionDeniedErrorthe moment it tries to open a port.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| "NODE_MODULE_VERSION mismatch" | Built for Node, not Electron's V8 | npx electron-rebuild |
App boots, but list() returns nothing | Sandbox blocks the binding | Disable sandbox for the main process or whitelist USB devices |
| Native module missing in packaged app | asar swallowed it | Add to asarUnpack in builder config |