Preparing Productive Electron Codebase
This is not tutorial. This is a minimal note of the electron architecture that I use.
Core Architecture
- Electron React Boilerplate (Perhaps I’d migrate to electron-vite next, get things done is more important for now)
- trpc.io (via
electron-trpc
) - hono.dev for backend (if require internet API), deployed to Cloudflare Worker
- Xstate
React related
@tanstack/react-query
then integrated with trpc
Architecture
- Server code (hono.dev)
- App code (electron)
- Main processes
- Renderer processes
For each of those parts, we communicate over trpc.
- Server code expose TrpcRouter
AppRouter
to be consumed by main process (Utils.trpcInternet
) and renderer processutils/trpc-internet-react
- Main process also expose TrpcRouter
MainRouter
to be consumed by renderer processesutils/trpc-main
Possible communication:
- Main -> Internet Server (Cloudflare) via
trpcInternet
- Renderer -> Internet Server (Cloudflare) via
trpcInternetReact
- Renderer -> Main via
trpcMain
Machine
Main or Renderer process can have their own machine, where renderer machine will only responsible for UI related state and Main machine will be responsible the whole app state / global state.
To communicate from Renderer UI to Main Machine, we will use Trpc.
Possible communication:
- Renderer ->
trpcMain
dispatch event -> Main Machine - Main -> direct dispatch -> Main Machine
- Renderer -> direct dispatch -> Renderer Machine
What about Main to Renderer Machine? (Use standard window.webContents.send
), and renderer listen to dispatch to renderer machine.
- We use standard IPC communication,
window.webContents.send
and then on preload we handle itipcRenderer.on
that also can be accessed in UI- We can setup mechanism to sync Main Machine state inside Renderer process, such that it can be accessed directly.
Other important packages
- Zod
- @xstate/immer
Quirks
When implementing trpcInternet
we got error, No fetch
implementation found. This because node has no fetch
implementation, to solve it we use package electron-fetch
and and replace internal trpc implementation with fetch
from electron-fetch
Why we consider to migrate to electron-vite
- It is newer (this can be good or bad at the same time)
- After initial trying, it works smoothly
- Typescript auto import works better especially in renderer process
- Configuration seems simpler and well documented
- Folder structure is minimal and preload is separated
- I think we have better control over package bundler config (I suspect, the ESM ERR REQUIRE can be solved trivially in
electron-vite
)