Пособие: Electron — создаём десктопное приложение с нуля
Это подробное пособие по Electron — фреймворку для создания кроссплатформенных десктопных приложений на HTML, CSS и JavaScript.
1. Что такое Electron?
Electron позволяет разрабатывать нативные десктопные приложения для Windows, macOS и Linux, используя веб-технологии. В основе лежит Node.js + Chromium. Примеры известных приложений: Visual Studio Code, Slack, Discord, Figma, Notion.
Как это работает?
Каждое приложение Electron состоит из двух процессов:
- Main (главный процесс) — отвечает за создание окон, управление жизненным циклом приложения, доступ к API операционной системы. Имеет полный доступ к Node.js.
- Renderer (процесс рендеринга) — показывает интерфейс (HTML/CSS/JS). Каждое окно — отдельный процесс рендеринга. Может использовать часть API Node.js (ограниченно).
Для обмена данными между процессами используется IPC (Inter-Process Communication).
2. Подготовка окружения
Убедитесь, что установлен Node.js (версия 14 или выше):
node -v
Создайте папку для проекта и инициализируйте его:
mkdir my-electron-app cd my-electron-app npm init -y
Установите Electron как зависимость:
npm install electron --save-dev
В файле package.json измените точку входа и добавьте скрипт запуска:
{
"name": "my-electron-app",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron ."
}
}
3. Минимальное приложение
Создайте три файла: main.js (главный процесс), index.html (интерфейс), renderer.js (логика окна).
main.js
const { app, BrowserWindow } = require('electron');
const path = require('node:path');
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'), // безопасный мост
// nodeIntegration: false (по умолчанию безопасно)
}
});
win.loadFile('index.html');
// win.webContents.openDevTools(); // для отладки
}
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Моё Electron приложение</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Привет, Electron!</h1>
<button id="infoBtn">Информация о системе</button>
<p id="output"></p>
<script src="renderer.js"></script>
</body>
</html>
preload.js (мост для безопасного общения с main)
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
getSystemInfo: () => ipcRenderer.invoke('get-system-info')
});
renderer.js
const btn = document.getElementById('infoBtn');
const output = document.getElementById('output');
btn.addEventListener('click', async () => {
const info = await window.electronAPI.getSystemInfo();
output.textContent = `OS: ${info.os}, платформа: ${info.platform}, версия Node: ${info.nodeVersion}`;
});
Теперь добавим обработку IPC в main.js:
const { app, BrowserWindow, ipcMain } = require('electron');
// ... createWindow и прочее
ipcMain.handle('get-system-info', () => {
return {
os: process.platform,
platform: process.platform,
nodeVersion: process.versions.node
};
});
4. Запуск
Выполните в терминале:
npm start
Откроется окно с кнопкой. После нажатия получите данные о системе.
5. Разбираем ключевые концепты
Главный процесс (main.js)
- Один главный процесс на всё приложение.
- Управляет окнами (BrowserWindow), меню, диалогами (открыть/сохранить файл), треем.
- Перехватывает события системы: ready, window-all-closed, before-quit.
Процесс рендерера (каждое окно)
- Загружает HTML, работает как обычное веб-окно.
- Из соображений безопасности не имеет прямого доступа к Node.js (по умолчанию). Чтобы безопасно вызывать функции main-процесса, используется preload.js и contextBridge.
IPC (межпроцессное взаимодействие)
- Одностороннее (renderer → main): ipcRenderer.send + ipcMain.on.
- Двустороннее (запрос-ответ): ipcRenderer.invoke + ipcMain.handle (как в примере выше).
- Отправка из main в renderer: win.webContents.send('event-name', data) + в renderer через ipcRenderer.on.
6. Добавляем фишки: диалоги, доступ к файлам, меню
Простой диалог выбора файла (main.js)
const { dialog } = require('electron');
ipcMain.handle('select-file', async () => {
const result = await dialog.showOpenDialog({
properties: ['openFile']
});
return result.filePaths[0];
});
В preload.js добавить экспорт selectFile: () => ipcRenderer.invoke('select-file'), в renderer.js вызвать.
Создание нативного меню (main.js)
const { Menu } = require('electron');
const template = [
{
label: 'Файл',
submenu: [
{ label: 'Открыть', click: () => console.log('Открыть') },
{ role: 'quit', label: 'Выйти' }
]
}
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
Работа с файловой системой (через IPC)
Из renderer-процесса нельзя напрямую использовать fs. Но можно сделать обёртку в main:
ipcMain.handle('write-file', (event, path, content) => {
const fs = require('fs');
fs.writeFileSync(path, content);
return true;
});
7. Упаковка и распространение
Для сборки готового приложения используйте electron-builder или electron-packager.
Установка electron-builder
npm install electron-builder --save-dev
В package.json добавьте:
"build": {
"appId": "com.example.myapp",
"productName": "Моё приложение",
"directories": {
"output": "dist"
},
"files": [
"**/*",
"!node_modules/.bin"
],
"win": {
"target": "nsis",
"icon": "icon.ico"
},
"mac": {
"target": "dmg",
"icon": "icon.icns"
},
"linux": {
"target": "AppImage",
"icon": "icon.png"
}
}
Добавьте скрипт в package.json:
"scripts": {
"dist": "electron-builder",
"dist:win": "electron-builder --win",
"dist:mac": "electron-builder --mac",
"dist:linux": "electron-builder --linux"
}
Затем выполните npm run dist. Готовые установщики появятся в папке dist/.
8. Продвинутые советы и best practices
- Безопасность – всегда выключайте nodeIntegration: false, используйте contextIsolation: true (по умолчанию в современных версиях), не загружайте удалённый HTML.
- Отладка – используйте Ctrl+Shift+I (DevTools) в окне или win.webContents.openDevTools() в коде.
- Горячая перезагрузка – установите electron-reload для разработки.
- Работа с базами данных – используйте sqlite3 или better-sqlite3 в главном процессе, общайтесь через IPC.
- Автообновление – electron-updater (часть электрон-билдера).
- Управление состоянием – можно использовать Redux, MobX или просто localStorage / electron-store для хранения настроек.
9. Пример: приложение-заметки с сохранением в файл
Идея для закрепления:
- Главное окно с textarea и кнопкой «Сохранить».
- Диалог выбора папки (через dialog.showSaveDialog).
- Main получает путь и содержимое, сохраняет текст в файл.
- Добавить меню «Файл / Открыть» для загрузки заметки.
Это покроет все базовые механизмы Electron.
10. Где узнать больше?
- Официальная документация Electron – полный гайд, примеры, API.
- Electron Fiddle – интерактивная песочница.
- awesome-electron – коллекция инструментов, библиотек и примеров.
Поздравляю! Теперь у вас есть фундамент для создания настольных приложений на веб-технологиях. Начинайте с простых утилит, постепенно добавляя нативные возможности — диалоги, уведомления, трей, горячие клавиши. Удачи в разработке!