quartz/content/01-Sessions/Session 4 - IPC Communication.md
Mohammad Jarrar dec3e85fe2 ll
2026-03-15 07:36:20 +03:00

2.9 KiB

tags session duration status
electron
ipc
preload
contextBridge
security
4 2 hours ready

Session 4 — IPC: Making the Two Processes Talk

🎯 Objectives

  • Understand why IPC exists and why it's necessary
  • Send messages from Renderer → Main and back
  • Use preload.js and contextBridge safely
  • Wire a full two-way communication flow

🧠 Concepts Covered

Why IPC?

The Renderer runs in a sandboxed browser context. It cannot directly call fs.readFile() or access Node.js. IPC is the secure message-passing bridge.

Renderer → ipcRenderer.send('open-file') →
Main    → ipcMain.on('open-file', handler) →
Main    → win.webContents.send('file-content', data) →
Renderer → ipcRenderer.on('file-content', handler)

The Secure Way: preload.js + contextBridge

// preload.js — runs in a special context with BOTH Node and DOM access
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  openFile: () => ipcRenderer.invoke('open-file'),
  saveFile: (content) => ipcRenderer.invoke('save-file', content),
  onFileLoaded: (callback) => ipcRenderer.on('file-loaded', callback)
})
// main.js — handles the requests
const { ipcMain, dialog } = require('electron')
const fs = require('fs')

ipcMain.handle('open-file', async () => {
  const result = await dialog.showOpenDialog({ ... })
  if (!result.canceled) {
    return fs.readFileSync(result.filePaths[0], 'utf-8')
  }
})

ipcMain.handle('save-file', async (event, content) => {
  const result = await dialog.showSaveDialog({})
  if (!result.canceled) {
    fs.writeFileSync(result.filePath, content)
    return true
  }
})
// renderer (index.html script) — uses the exposed API
document.getElementById('open-btn').addEventListener('click', async () => {
  const content = await window.electronAPI.openFile()
  document.getElementById('editor').value = content
})

invoke vs send

ipcRenderer.send ipcRenderer.invoke
Fire and forget Returns a Promise
One-way Two-way (request/response)
Use for events Use for data fetching

🛠 Hands-on Exercise — Wire the Notepad (60 min)

Complete the Notepad from Session 3 using proper IPC:

  1. Set up preload.js with contextBridge
  2. Add webPreferences: { preload: ... } to BrowserWindow
  3. Expose openFile and saveFile via electronAPI
  4. Wire up Open and Save buttons in the renderer
  5. Bonus: Add a word count display that updates as you type

⚠️ Common Mistakes

  • Forgetting to set preload in webPreferences
  • Using nodeIntegration: true (insecure, avoid it)
  • Trying to require('fs') in renderer directly

📦 Resources