Розробка десктоп-додатку на Electron
Розробка десктопного додатку на Electron під ключ — ефективний спосіб створити кроссплатформний додаток для Windows, macOS та Linux з єдиною кодовою базою. Додаток гальмує на Windows, а на macOS виглядає чужорідно? Це типова проблема кроссплатформної розробки. Electron вирішує її: наші інженери за 5 років побудували понад 50 успішних проєктів — від корпоративних чатів до систем автоматизації. Досвід гарантує стабільний продукт з мінімальним часом виходу на ринок.
Electron скорочує час розробки в 3-4 рази порівняно з нативними рішеннями, а розмір дистрибутива ми оптимізуємо до 50-70 МБ за рахунок налаштування збірки та виключення невикористовуваних модулів. VS Code, Slack, Figma, GitHub Desktop — всі вони написані на Electron.
Чому Electron, а не Tauri?
Tauri дає менший розмір (5-20 МБ) та вищу продуктивність, але вимагає знань Rust для роботи з бекендом. Якщо ваша команда володіє TypeScript і ви хочете швидше запустити MVP, Electron залишається практичним вибором. Для проєктів з жорсткими обмеженнями по пам'яті або розміру дистрибутива Tauri може бути альтернативою, але для складного UI з інтеграцією веб-технологій Electron зручніше.
| Критерій | Electron | Tauri | Нативне (Qt/SwiftUI) |
|---|---|---|---|
| Розмір дистрибутива | 80-150 МБ | 5-20 МБ | 20-50 МБ |
| Продуктивність | Середня | Висока | Максимальна |
| Стек розробки | JS/TS/HTML/CSS | Rust + Web | С++/Swift/Котлін |
| Складність розробки | Низька | Середня | Висока |
Як прискорити завантаження Electron-додатку?
Завантаження часто страждає через великий стартовий пакет. Ми застосовуємо lazy-loading для модулів рендерера, код-спліттинг через Webpack або Vite та асинхронне завантаження важких бібліотек. Використання React Server Components в Electron: RSC можна рендерити в main-процесі та передавати результат в renderer, що скорочує час інтерактивності до 40%. Додатково налаштовуємо backgroundThrottling: false для фонових операцій та використовуємо Web Workers для розрахунків, щоб не блокувати UI. Після оптимізації швидкість завантаження збільшується до 60%.
Як забезпечити безпеку IPC?
IPC — точка входу для атак. Основні правила: contextIsolation: true, nodeIntegration: false, sandbox: true та обмежений preload-скрипт. Валідація всіх повідомлень в main-процесі через schema validation (наприклад, Zod). В одному проєкті ми закрили XSS-вразливість, перевіряючи типи аргументів на стороні main. За даними документації Electron з безпеки, контекстна ізоляція знижує ризики на 90%.
Архітектура: Main та Renderer процеси
Electron розділяє код на два ізольованих процеси:
Main process — Node.js середовище, має доступ до файлової системи, ОС, нативних API. Керує вікнами, системним треєм, нативними меню.
Renderer process — Chromium, рендерить веб-контент. Без прямого доступу до Node.js (якщо не включений nodeIntegration: true, що небезпечно). Спілкування з main — тільки через IPC.
// main/index.js
const { app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
titleBarStyle: 'hiddenInset', // macOS — кастомний заголовок
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true, // обов'язково для безпеки
nodeIntegration: false, // відключити для безпеки
sandbox: true
}
});
if (process.env.NODE_ENV === 'development') {
mainWindow.loadURL('http://localhost:3000');
mainWindow.webContents.openDevTools();
} else {
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'));
}
mainWindow.on('closed', () => { mainWindow = null; });
}
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
Preload script: безпечний міст
// main/preload.js
const { contextBridge, ipcRenderer } = require('electron');
// Експортуємо тільки потрібне API в renderer
contextBridge.exposeInMainWorld('electronAPI', {
// Файлова система
openFile: () => ipcRenderer.invoke('dialog:openFile'),
saveFile: (content) => ipcRenderer.invoke('fs:saveFile', content),
// Системні функції
getVersion: () => ipcRenderer.invoke('app:getVersion'),
minimize: () => ipcRenderer.send('window:minimize'),
maximize: () => ipcRenderer.send('window:maximize'),
close: () => ipcRenderer.send('window:close'),
// Підписка на події з main
onUpdateAvailable: (callback) => {
const listener = (_, info) => callback(info);
ipcRenderer.on('update:available', listener);
return () => ipcRenderer.removeListener('update:available', listener);
}
});
// main/ipc-handlers.js
const { ipcMain, app, dialog, BrowserWindow } = require('electron');
const fs = require('fs/promises');
ipcMain.handle('dialog:openFile', async () => {
const { canceled, filePaths } = await dialog.showOpenDialog({
filters: [
{ name: 'Text Files', extensions: ['txt', 'md'] },
{ name: 'All Files', extensions: ['*'] }
]
});
if (canceled) return null;
const content = await fs.readFile(filePaths[0], 'utf-8');
return { path: filePaths[0], content };
});
ipcMain.handle('app:getVersion', () => app.getVersion());
ipcMain.on('window:minimize', (event) => {
BrowserWindow.fromWebContents(event.sender)?.minimize();
});
Упаковка та дистрибуція
electron-builder — стандарт для збірки інсталяторів:
# electron-builder.yml
appId: com.yourcompany.myapp
productName: My Application
directories:
output: release/
files:
- main/**
- renderer/dist/**
- '!**/*.map'
mac:
category: public.app-category.productivity
icon: resources/icon.icns
target:
- dmg
- zip
win:
icon: resources/icon.ico
target:
- nsis
- portable
linux:
icon: resources/icons/
target:
- AppImage
- deb
- rpm
Поширені проблеми при розробці на Electron
-
nodeIntegration: true— відкриває Node.js в рендерері, що критично небезпечно. Завжди відключайте. - Забагато IPC-викликів — кожен виклик асинхронний, перевантаження потоків гальмує UI. Групуйте дані пакетами.
- Ігнорування
contextIsolation— preload без ізоляції дає доступ до Node.js. Вмикайте обов'язково. - Великий bundle — невикористовувані модулі роздувають дистрибутив. Використовуйте tree-shake, це знижує споживання пам'яті на 30%.
- Прямий доступ до файлової системи з renderer — використовуйте IPC та preload.
Процес роботи
- Аналітика — розбираємо бізнес-вимоги, вибираємо стек (React/Vue, electron-vite, etc.).
- Проектування — прототип UI, схема IPC-каналів, архітектура зберігання даних.
- Реалізація — розробка main- та renderer-процесів, налаштування автооновлення.
- Тестування — перевірка на всіх платформах, виправлення edge-case.
- Деплой — збірка інсталяторів, публікація або передача білдів.
Терміни та що входить в роботу
| Етап | Тривалість | Результат |
|---|---|---|
| MVP (базовий додаток) | 1-2 тижні | Робочий прототип з UI та одним IPC-сценарієм |
| Повноцінний продукт | 3-6 тижнів | Повний функціонал, автооновлення, збірка під 3 платформи |
| Оптимізація та аудит | 1-2 тижні | Зменшення розміру, покращення продуктивності |
Зазначимо: що входить у вартість:
- Вихідний код та документація
- Доступ до репозиторію (GitLab/GitHub)
- Налаштована CI/CD-збірка
- Інструкція з розгортання
- Підтримка протягом місяця після релізу
Замовте розробку під ключ — ми продумаємо архітектуру, налаштуємо автоматичне оновлення та упакуємо в інсталятори для всіх платформ. Отримайте консультацію по вашому проєкту: зв'яжіться з нами для оцінки.







