Архитектура Electron
Electron можно представить как:
Многопроцессный контейнер приложений со встроенным браузерным движком (Chromium) и средой выполнения Node.js,
Настольные приложения, объединяющие "веб-страницы + системные возможности" и взаимодействующие через межпроцессное взаимодействие (IPC).
Его основные компоненты:
| Роль | Описание | Аналогия |
|---|---|---|
| Главный процесс (main process) | Мозг Electron, управляющий жизненным циклом приложения, создающий окна и вызывающий системные API | Менеджер процессов ОС |
| Процесс рендеринга | Среда веб-страницы (HTML, CSS, JS), запускаемая каждым окном | Вкладка браузера |
| Скрипт предзагрузки | Выполняется перед рендерингом, может связать API главного процесса для использования веб-страницами | Безопасность «промежуточный слой» |
| IPC (межпроцессное взаимодействие) | Канал связи между главным процессом и процессами рендеринга | телефонная линия |
| Объект BrowserWindow | «Контейнер окна», создаваемый главным процессом, который загружает веб-страницы внутри себя | Окно браузера |
| Модуль приложения | Управляет жизненным циклом приложения (запуск, выход) | Главный контроллер |
Главный процесс
Главный процесс — это «мозг» приложения Electron; у каждого приложения Electron есть ровно один главный процесс. Он отвечает за:
- Создание и управление окнами приложения(Процесс рендеринга)
- Обработка жизненного цикла приложения(Запуск, Выход, Переключение переднего/фонового режима)
- Взаимодействие с нативными API операционной системы
- Управление компонентами системного уровня, такими как меню и диалоговые окна
Пример
const { app, BrowserWindow } = require('electron');
function createWindow() {
// Создать окно браузера
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
// Загрузить index.html приложения
mainWindow.loadFile('index.html');
}
// Вызывается, когда Electron завершает инициализацию
app.whenReady().then(createWindow);
Процесс рендеринга
Процесс рендеринга отвечает за отображение пользовательского интерфейса; каждое окно Electron — это независимый процесс рендеринга:
- Работает в среде браузера Chromium
- Используйте HTML, CSS и JavaScript для создания интерфейсов
- Каждое окно — это независимый процесс, и они не влияют друг на друга
- Взаимодействует с главным процессом через IPC
Пример
<!DOCTYPE html>
<html>
<head>
<title>Моё приложение Electron</title>
</head>
<body>
<h1>Привет, Electron!</h1>
<button id="btn">Нажми меня</button>
<script>
// JavaScript в процессе рендеринга
document.getElementById('btn').addEventListener('click', () => {
alert('Кнопка была нажата!');
});
</script>
</body>
</html>
Предзагрузочные скрипты
Предзагрузочный скрипт — это "мост", соединяющий главный процесс и процесс рендеринга:
- Выполняется до загрузки веб-страницы в процессе рендеринга
- Имеет доступ к API Node.js и DOM
- Безопасно предоставляйте API процессу рендеринга через contextBridge
Пример
const { contextBridge, ipcRenderer } = require('electron');
// Предоставить безопасный API процессу рендеринга
contextBridge.exposeInMainWorld('electronAPI', {
showDialog: (message) => ipcRenderer.invoke('show-dialog', message)
});
Межпроцессное взаимодействие (IPC)
Шаблоны IPC-взаимодействия
IPC(межпроцессное взаимодействие)Является ядром взаимодействия Electron.
Поскольку главный процесс и процесс рендеринга независимы, данные должны передаваться через IPC.

Направление взаимодействия
| Type | Прослушивание главного процесса | Отправлено процессом рендеринга |
|---|---|---|
| Процесс рендеринга → Главный процесс | ipcMain.on(channel, handler) |
ipcRenderer.send(channel, data) |
| Главный процесс → Процесс рендеринга | event.sender.send(channel, data) |
ipcRenderer.on(channel, callback) |
Пример базового взаимодействия
Код главного процесса:
Пример
// Прослушивание сообщений от процесса рендеринга
ipcMain.handle('show-dialog', async (event, message) => {
const result = await dialog.showMessageBox({
type: 'info',
message: message,
buttons: ['OK', 'Cancel']
});
return result;
});
Код процесса рендеринга:
Пример
document.getElementById('btn').addEventListener('click', async () => {
const result = await window.electronAPI.showDialog('Привет, Electron!');
console.log('Пользователь нажал:', result.response);
});
Преимущества и особенности архитектуры
Сравнение преимуществ
| Особенности | Electron | Традиционная разработка настольных приложений |
|---|---|---|
| Технология разработки | Веб-технологии (HTML/CSS/JS) | Нативные языки (C++/C#/Java) |
| Кроссплатформенная поддержка | Разработка один раз, запуск на нескольких платформах | Требует отдельной разработки для каждой платформы |
| Эффективность разработки | Высокая, использует существующую веб-экосистему | Ниже, требует изучения специфичных для платформы технологий |
| Производительность | Относительно низкая, потребляет больше ресурсов | Высокая, нативная производительность |
| Размер установщика | Большой (включает Chromium) | меньше |
Основные возможности
- Кроссплатформенная согласованность: Приложение выглядит и ведёт себя одинаково во всех операционных системах
- Использование веб-экосистемы: Можно напрямую использовать npm-пакеты и веб-фреймворки
- Быстрое прототипирование: На основе знакомых веб-технологий, короткий цикл разработки
- Богатые API: Предоставляет полный набор API для доступа к нативным возможностям системы
Примеры практического применения
Давайте создадим простое приложение файлового менеджера, чтобы продемонстрировать архитектуру Electron:
Главный процесс (main.js):
Пример
const fs = require('fs').promises;
const path = require('path');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1000,
height: 700,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true
}
});
mainWindow.loadFile('index.html');
}
// Обработка чтения файла
ipcMain.handle('read-file', async (event, filePath) => {
try {
const content = await fs.readFile(filePath, 'utf-8');
return { success: true, content };
} catch (error) {
return { success: false, error: error.message };
}
});
// Обработка выбора файла
ipcMain.handle('select-file', async () => {
const result = await dialog.showOpenDialog(mainWindow, {
properties: ['openFile'],
filters: [
{ name: 'Текстовый файл', extensions: ['txt', 'md', 'js', 'html', 'css'] }
]
});
return result;
});
app.whenReady().then(createWindow);
Скрипт предзагрузки (preload.js):
Пример
contextBridge.exposeInMainWorld('fileAPI', {
readFile: (filePath) => ipcRenderer.invoke('read-file', filePath),
selectFile: () => ipcRenderer.invoke('select-file')
});
Процесс рендеринга (index.html):
Пример
<html>
<head>
<title>Простой файловый менеджер</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.container { max-width: 800px; margin: 0 auto; }
button { padding: 10px 15px; margin: 5px; cursor: pointer; }
#content { border: 1px solid #ccc; padding: 15px; margin-top: 10px;
min-height: 300px; white-space: pre-wrap; }
</style>
</head>
<body>
<div class="container">
<h1>Простой файловый менеджер</h1>
<button id="selectBtn">Выбрать файл</button>
<button id="clearBtn">Очистить содержимое</button>
<div>
<h3>Содержимое файла:</h3>
<div id="content">Пожалуйста, выберите файл...</div>
</div>
</div>
<script>
const selectBtn = document.getElementById('selectBtn');
const clearBtn = document.getElementById('clearBtn');
const contentDiv = document.getElementById('content');
selectBtn.addEventListener('click', async () => {
const result = await window.fileAPI.selectFile();
if (!result.canceled && result.filePaths.length > 0) {
const filePath = result.filePaths[0];
const fileResult = await window.fileAPI.readFile(filePath);
if (fileResult.success) {
contentDiv.textContent = `Путь к файлу: ${filePath}\n\n${fileResult.content}`;
} else {
contentDiv.textContent = `Не удалось прочитать файл: ${fileResult.error}`;
}
}
});
clearBtn.addEventListener('click', () => {
contentDiv.textContent = 'Пожалуйста, выберите файл...';
});
</script>
</body>
</html>
Другие важные модули (доступны в основном процессе)
| имя модуля | Функция |
|---|---|
app |
Управление жизненным циклом приложения (запуск/выход) |
Menu / MenuItem |
Создание строки меню приложения |
Tray |
Значок системного трея |
Notification |
Системное уведомление |
dialog |
Диалоговое окно открытия/сохранения файла |
shell |
Вызов системной программы по умолчанию для открытия файлов или URL |
nativeImage |
Работа с изображениями (значками) |
clipboard |
Работа с содержимым буфера обмена |
powerMonitor |
Прослушивание системных событий питания |
screen |
Получение информации об экране (поддержка нескольких мониторов) |
Архитектура безопасности и изоляция песочницы
Поскольку процессы рендеринга могут запускать веб-страницы, чтобы предотвратить атаки вредоносного кода на систему, Electron реализует следующие механизмы безопасности:
| Политика | Описание |
|---|---|
| Отключение NodeIntegration | Defaultfalse, предотвращая прямой вызов системных API веб-страницами. |
| Включите ContextIsolation | Заставьте скрипты страницы и Preload APIs выполняться в изолированном контексте. |
| Preload + contextBridge | Чётко контролируйте безопасные API, предоставляемые фронтенду. |
| Content Security Policy (CSP) | Ограничьте источники скриптов для предотвращения XSS. |
| режим sandbox | Песочницу можно включить, чтобы полностью изолировать процесс рендеринга. |
| Проверяйте удалённые URL | Недоверенное удалённое содержимое должно проходить проверку по белому списку. |
Поток выполнения (от запуска до рендеринга)
1、启动应用 (electron .)
↓
2、执行 main.js(主进程启动)
↓
3、app.whenReady() 触发,创建 BrowserWindow
↓
4、BrowserWindow 启动新的渲染进程(Chromium 实例)
↓
5、preload.js 先执行(在隔离上下文中)
↓
6、index.html 加载并显示(运行前端框架)
↓
7、渲染进程通过 IPC 调用主进程逻辑
↓
8、主进程处理请求、返回结果
↓
9、用户关闭窗口 → 主进程监听 → app.quit()
Модель главного-подчинённого многоконного режима (параллельная многопроцессность)
- У приложения Electron всегда есть толькоГлавный процесс;
- Но может иметьНесколько процессов рендеринга (каждое окно независимо);
- Связь между ними должна проходить через ретрансляцию главного процесса или использовать
ipcMain.handleВыполните асинхронное мостовое соединение.
Схема:
主进程 (Main) ├── 窗口1 → 渲染进程A (index.html) ├── 窗口2 → 渲染进程B (settings.html) └── 窗口3 → 渲染进程C (dashboard.html)
Внутренние основные компоненты Electron (базовые зависимости)
| Уровень | Технология |
|---|---|
| Слой рендеринга UI | Chromium(Blink + V8) |
| Слой системного интерфейса | Node.js(libuv + привязки C++) |
| Слой управления процессами | Ядро Electron (C++ + JavaScript) |
| Слой прикладной логики | Ваш код JS/TS (Main + Renderer) |
Другие расширенияВаш JS-код выполняется в среде Node, инкапсулированной Electron, а интерфейс рендеринга работает в Chromium WebView.