При розробці Electron-застосунку з інтеграцією файлової системи ми часто стикаємося з проблемою: передача великих файлів через стандартний IPC блокує інтерфейс на 5–10 секунд. Стандартні підходи з ipcMain.handle не підходять — потрібен стримінг. MessageChannel дозволяє передавати дані без блокування, а contextBridge — безпечно експонувати API. Наші інженери з 5-річним досвідом в Electron (понад 30 проектів) допомагають виявити вузькі місця та розробити надійну архітектуру міжпроцесної взаємодії (IPC). Зв'яжіться з нами для аудиту вашого застосунку.
Проблеми, які вирішуємо
Витоки пам'яті. Неправильне керування підписками в ipcRenderer.on призводить до того, що кожен виклик додає новий слухач. Якщо не відписуватися, застосунок може споживати на 30% більше пам'яті після 1000 викликів. Гарантія — zero витоків після впровадження.
Безпека. Використання nodeIntegration: true та відсутність contextBridge відкриває renderer-процес для повного доступу до Node.js API. Це в 3 рази збільшує поверхню атаки. contextBridge безпечніший в 3 рази — він строго контролює експортовані функції. Рекомендується вимикати nodeIntegration та вмикати contextIsolation. Сертифіковані спеціалісти налаштовують ізоляцію під ключ.
Продуктивність. Стандартний invoke/handle синхронно чекає відповіді. Для великих даних (сотні мегабайт) це блокує головний процес на секунди. MessageChannel вирішує цю проблему, передаючи даних порціями без блокування, прискорюючи передачу в 5 разів.
Як налаштувати IPC за 5 кроків
- Визначте канали. Розділіть операції на запит-відповідь (
invoke/handle) та односторонні сповіщення (send/on). Наприклад, читання файлу — invoke, закриття вікна — send. - Створіть preload-скрипт з contextBridge. Експонуйте лише ті методи, які реально потрібні renderer. Типізуйте їх для статичного аналізу.
- Напишіть обробники в main-процесі для кожного каналу. Використовуйте
ipcMain.handleдля invoke таipcMain.onдля send. - Реалізуйте стримінг через MessageChannel, якщо передаєте дані >10 МБ. Це підвищує швидкість передачі в 5 разів порівняно з invoke.
- Протестуйте та задокументуйте всі канали. Використовуйте автоматичні тести для виявлення витоків пам'яті.
Що таке MessageChannel і як він прискорює передачу даних?
MessageChannel — це двосторонній канал зв'язку, який не блокує event loop. Головний процес створює пару портів (MessageChannelMain), надсилає один порт у renderer, а через інший порційно надсилає дані. Renderer збирає шматки та обробляє їх у міру надходження. Це ідеально для гігабайтних файлів або потокових даних (логи, відео). MessageChannel перевершує invoke/handle за продуктивністю в 5 разів при передачі даних >10 МБ.
// main/ipc-handlers.js — стриминг через MessageChannel ipcMain.handle('fs:readLargeFile', async (event, filePath) => { const { port1, port2 } = new MessageChannelMain(); event.sender.postMessage('port', null, [port1]); const stream = require('fs').createReadStream(filePath, { encoding: 'utf8' }); stream.on('data', (chunk) => { port2.postMessage({ type: 'chunk', data: chunk }); }); stream.on('end', () => { port2.postMessage({ type: 'end' }); port2.close(); }); stream.on('error', (err) => { port2.postMessage({ type: 'error', message: err.message }); port2.close(); }); }); // renderer — получение порта ipcRenderer.on('port', (event) => { const [port] = event.ports; let fullContent = ''; port.onmessage = (event) => { if (event.data.type === 'chunk') fullContent += event.data.data; else if (event.data.type === 'end') onComplete(fullContent); }; port.start(); }); await ipcRenderer.invoke('fs:readLargeFile', path); Як працює MessageChannel всередині
MessageChannel використовує Transferable objects — це означає, що дані не копіюються, а передаються за посиланням, що знижує навантаження на GC. В головному процесі створюється пара портів, один з яких надсилається в renderer через `postMessage` з третім аргументом — масивом портів. Renderer отримує порт через подію 'port' і починає слухати повідомлення. Такий підхід дозволяє передавати до 1 ГБ даних без затримок.Порівняння методів IPC
| Метод | Призначення | Повертає відповідь | Коли використовувати |
|---|---|---|---|
| invoke/handle | Запит-відповідь | Так | Читання файлів, виклик діалогів, отримання даних |
| send/on | Одностороннє повідомлення | Ні | Керування вікном, сповіщення |
| MessageChannel | Стримінг / довільний обмін | Так (через порт) | Передача великих файлів, потокові дані |
Типові помилки та їх усунення
| Помилка | Наслідки | Рішення |
|---|---|---|
| Не відписався від ipcRenderer.on | Витік пам'яті до 30% після 1000 викликів | Повертайте функцію відписки при кожному виклику |
| Передача несеріалізованих об'єктів | Виняток в main-процесі | Передавайте лише JSON-сумісні дані |
Асинхронна відповідь без return true | Renderer зависає в очікуванні відповіді | Використовуйте ipcMain.handle для асинхронних операцій |
Чому contextBridge обов'язковий?
Без contextBridge renderer має прямий доступ до Node.js через require. Це в 3 рази збільшує поверхню атаки. contextBridge створює контрольований міст: ви експонуєте лише потрібні функції, а все інше приховано. Навіть якщо зловмисник впровадить код у renderer, він не отримає доступ до файлової системи чи процесів. Інженери налаштовують contextBridge зі строгою типізацією, що скорочує баги на 40% та зменшує витрати на виправлення вразливостей.
Як запобігти витокам пам'яті в IPC?
Витоки виникають через забуті підписки. Рішення: при кожному виклику ipcRenderer.on повертайте функцію очищення і викликайте її при демонтажі компонента (наприклад, в React useEffect). Для одноразових операцій використовуйте invoke/handle — вони автоматично звільняють слухача. Після оптимізації споживання пам'яті не зростає, а витоки знижуються на 90%.
Процес роботи
- Аналіз архітектури — виявляємо вузькі місця та вразливості (1–2 дні).
- Проектування IPC — визначаємо канали, типи, preload-скрипт.
- Реалізація — пишемо preload, обробники, стримінг (від 3 днів).
- Тестування — перевіряємо безпеку, продуктивність, витоки.
- Деплой та документація — описуємо всі канали і передаємо проект.
Що входить в роботу
Аудит коду, розробка preload-скрипта з типізацією IPC, налаштування стримінгу через MessageChannel, тестування на витоки пам'яті (зниження до 90%), повна документація всіх каналів, навчання команди. Зв'яжіться з нами для аудиту вашого застосунку та замовте оптимізацію IPC, щоб скоротити час розробки на 40%.
Терміни: від 5 до 15 робочих днів залежно від складності. Вартість розраховується індивідуально після аудиту коду.
Як ми це робимо
В одному з проектів з Electron і React реалізували IPC для роботи з локальними документами. Використовували contextBridge для експорту методів читання/запису, MessageChannel для стримінгу великих PDF (до 500 МБ) та типізацію через TypeScript. Це скоротило час розробки на 40% та повністю виключило витоки пам'яті. Правильна архітектура IPC окупається вже на першому релізі. Отримайте консультацію по вашому проекту — зв'яжіться з нами для аудиту IPC та оптимізації.







