Conceptos básicos de Electron

La esencia de Electron es un framework de aplicaciones de escritorio multiproceso que combinaChromium (capa de renderizado)yNode.js (capa del sistema), logrando visualización de interfaz, control lógico y comunicación segura mediante un modelo de procesos independientes.

A continuación se muestra la arquitectura central de Electron, que muestra la relación entre el proceso principal, el proceso de renderizado, la comunicación IPC y Preload.

Proceso principal (A):

  • Ejecuta Node.js, controla las ventanas y la interacción con el sistema.
  • Usa BrowserWindow para crear procesos de renderizado.

Proceso de renderizado (B):

  • Cada ventana ejecuta HTML/CSS/JS de forma independiente para mostrar la interfaz.

Script de precarga (B2):

  • Se ejecuta antes de que se cargue el proceso de renderizado, conectando el proceso principal con la capa web.
  • Expone API de forma segura mediante contextBridge.

Comunicación IPC (flechas discontinuas):

  • El proceso principal y el proceso de renderizado se comunican bidireccionalmente mediante ipcMain e ipcRenderer.

Sistema operativo (C):

  • El proceso principal puede acceder a funciones del sistema, como archivos, bandeja, notificaciones, etc.


Proceso principal (Main Process)

El proceso principal es el "centro de comando" de la aplicación Electron y se ejecuta en el entorno Node.js.
Es responsable de crear ventanas, gestionar el ciclo de vida de la aplicación, llamar a las API del sistema y comunicarse con el proceso de renderizado.
Una vez que se inicia toda la aplicación, el sistema ejecuta primero el script del proceso principal (normalmentemain.js)。

Responsabilidades del proceso principal

  • Iniciar y salir de la aplicación
  • Crear y destruir BrowserWindow (ventanas)
  • Registrar menús, bandeja y atajos de teclado globales
  • Llamar a funciones del sistema operativo (sistema de archivos, notificaciones, diálogos)
  • Escuchar eventos enviados por el proceso de renderizado

Ciclo de vida del proceso principal

El ciclo de vida del proceso principal coincide con el ciclo de vida de la aplicación, desde elappmódulo comienza:

Ejemplo

const { app, BrowserWindow } = require('electron');

app.whenReady().then(() => {
  const win = new BrowserWindow({ width: 800, height: 600 });
  win.loadFile('index.html');
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});
  • app.whenReady()Se activa cuando Electron completa la inicialización.
  • window-all-closedSe activa cuando se cierran todas las ventanas.
  • app.quit()Sale de toda la aplicación.
  • Caso especial común en macOS: cuando el usuario cierra todas las ventanas, el programa sigue ejecutándose en segundo plano.

Explicación detallada del módulo app

appEl módulo se usa para controlar todo el ciclo de vida de la aplicación:

  • app.on('ready')Se activa cuando Electron termina de inicializarse.
  • app.quit()Sale de la aplicación.
  • app.getPath('userData')Obtiene la ruta del sistema.
  • app.setAppUserModelId(id)Establece el ID de la barra de tareas de Windows.
  • app.isPackagedDetermina si actualmente está empaquetado.

Gestión de ventanas de BrowserWindow

El proceso principal a través deBrowserWindowcrea ventanas visuales:

Ejemplo

const win = new BrowserWindow({
  width: 1024,
  height: 768,
  resizable: true,
  webPreferences: {
    preload: './preload.js',
    nodeIntegration: false
  }
});
  • width, heightDimensiones de la ventana
  • resizableSi se puede ajustar el tamaño
  • webPreferencesSe usa para configurar el comportamiento del proceso de renderizado

    • preloadScript de precarga
    • nodeIntegrationSi se permite que el proceso de renderizado use Node.js

Funciones nativas como menús, bandeja y diálogos

Electron proporciona varios módulos para acceder a las funciones del sistema:

  • Menu / MenuItemBarra de menús personalizada
  • TrayCrea el icono de la bandeja del sistema
  • DialogLlama al selector de archivos del sistema, cuadros de advertencia
  • NotificationNotificaciones nativas
  • shellAbrir enlaces o archivos externos, por ejemplo:

    const { dialog } = require('electron');
    dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] });

Proceso de renderizado (Renderer Process)

El proceso de renderizado se encarga de mostrar la interfaz y se ejecuta en el entorno Chromium.
CadaBrowserWindowtiene un proceso de renderizado independiente.

Características del proceso de renderizado

  • Basado en Chromium, ejecuta HTML/CSS/JS
  • Por defectono puede acceder directamente a las API de Node.js(por razones de seguridad)
  • Puede usar el stack de tecnologías web: Vue, React, Svelte, etc.
  • Cada ventana corresponde a un hilo independiente, no se afectan entre sí

Múltiples ventanas y múltiples procesos de renderizado

Cada ventana de Electron (BrowserWindow) iniciará un proceso de renderizado independiente:
Cerrar una ventana no afecta a otras ventanas, similar al modelo de múltiples pestañas del navegador.
Esto hace que la aplicación sea más segura y confiable durante la recuperación de fallos.

Carga y visualización de páginas web

El contenido del proceso de renderizado se carga desde el proceso principal:

win.loadFile('index.html');    // 加载本地页面
// 或者
win.loadURL('https://example.com'); // 加载远程网页

Limitaciones en el proceso de renderizado

  • Por razones de seguridad, no se pueden usar módulos de Node.js directamente (comofs、path)。
  • No se recomienda ejecutar cálculos de alta carga en el proceso de renderizado (congelará la UI).
  • La interacción con el sistema debe realizarse a través de comunicación IPC o API expuestas por preload.

Comunicación entre procesos (IPC)

Uno de los mecanismos centrales de Electron esla comunicación entre el proceso principal y el proceso de renderizado, llamadoIPC(Inter-Process Communication)。

ipcMain e ipcRenderer

  • ipcMain: se usa en el proceso principal para recibir mensajes.
  • ipcRenderer: se usa en el proceso de renderizado para enviar mensajes.

Ejemplo de comunicación unidireccional:

Ejemplo

// main.js
const { ipcMain } = require('electron');
ipcMain.on('ping', (event, arg) => {
  console.log(arg); // Salida "hello from renderer"
});

// renderer.js
const { ipcRenderer } = require('electron');
ipcRenderer.send('ping', 'hello from renderer');

Ejemplo de comunicación bidireccional (el proceso principal devuelve datos):

ipcMain.on('getVersion', (event) => {
  event.reply('getVersionResponse', app.getVersion());
});

Recepción en el proceso de renderizado:

ipcRenderer.on('getVersionResponse', (event, version) => {
  console.log(version);
});

Modo invoke/handle (recomendado)

Electron ofrece una forma más concisa de solicitudes asíncronas:

Proceso principal:

ipcMain.handle('get-app-path', () => app.getPath('userData'));

Proceso de renderizado:

const result = await ipcRenderer.invoke('get-app-path');
console.log(result);

Este método es similar afetchsolicitudes, evitando callbacks en múltiples capas.

Mejores prácticas para el envío de mensajes

  • Usarnombres de canal claros(como"user:getData")。
  • Evita transmitir objetos complejos (se recomienda JSON).
  • Los datos provenientes del proceso de renderizado deben validarse en cuanto a origen y tipo.
  • Intenta en la medida de lo posible medianteinvoke/handlelograr una comunicación estructurada.

Scripts de precarga (Preload Scripts)

El script de precarga se ejecuta antes de que se cree el proceso de renderizado, entre el proceso principal y la página web.
Su función es "puentear" de forma segura las funcionalidades de Node.js para la página de renderizado.

Función y significado de preload

  • Puede acceder a las API de Node.js (porque está en un contexto aislado)
  • Puede exponer de forma segura algunas API a la página de renderizado
  • Se usa comúnmente para lectura/escritura de archivos, obtención de rutas del sistema, transferencia de información de la aplicación, etc.
// preload.js
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  getAppVersion: () => ipcRenderer.invoke('getVersion')
});

Uso desde el proceso de renderizado:

// index.html
<script>
  window.electronAPI.getAppVersion().then(v => {
    console.log('App version:', v);
  });
</script>

Comunicación segura con contextBridge

contextBridgeEs una API segura proporcionada por Electron, que se usa para:

  • Exponer solo las funciones necesarias (mecanismo de lista blanca)
  • Evitar que páginas web maliciosas accedan al entorno Node.js
  • EncontextIsolation: trueTodavía se puede comunicar de forma segura en modo

Uso en modo sandbox

Si el sandbox está habilitado (sandbox: true), el proceso de renderizado no puede usar Node.js en absoluto.
En este caso, preload es el único puente, responsable de:

  • Recibir llamadas del lado de renderizado
  • Reenviar al proceso principal a través de IPC
  • Devolver el resultado al lado web

Resumen

Módulo Función Entorno de ejecución
Proceso principal (Main) Controla el ciclo de vida de la aplicación, las ventanas y las interfaces del sistema. Node.js
Proceso de renderizado (Renderer) Muestra la interfaz de usuario y ejecuta la lógica del frontend. Chromium
IPC Implementa la comunicación entre el proceso principal y el proceso de renderizado Canal bidireccional
Preload Puentea de forma segura Node y Web Capa intermedia

Entendido en una frase:
El proceso principal es como la "sala de control", el proceso de renderizado es como el "personal de cada ventana",
IPC es el "walkie-talkie", Preload es el "canal seguro filtrado".

Otras extensiones