Skip to main content

运行流程运行流程

运行的流程

Electron 运行的流程

主进程和渲染进程

关于主进程和渲染器进程

  • package.json 中定义的入口被称为主进程。 在主进程中实例化 BrowserWindow 创建的 Web 页面被称为渲染进程。 一个 Electron 应用只有一个主进程,但是可以有多个渲染进程, 每个 Electron 中的 web 页面运行在它自己的渲染进程中。

  • 主进程使用 BrowserWindow 实例创建页面。 每个 BrowserWindow 实例都在自己的 渲染进程里运行页面。 当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。

Electron 运行的流程

  • 进程(了解):进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
  • 线程(了解):在⼀一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是: 线程是“一个进程内部的控制序列”。
  • 线程和进程(了解):一个程序至少有一个进程,一个进程至少有一个线程。

主进程和渲染进程案例

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

const createWindow = () => {
const mainWindow = new BrowserWindow({ width: 600, height: 400 });
mainWindow.loadFile(path.join(__dirname, "index.html"));

const secondWindow=new BrowserWindow({
width: 300,
height: 200,
parent: mainWindow,
});

secondWindow.loadFile(path.join(__dirname, "second.html"));

}

// 监听应用的启动事件
app.on("ready", createWindow)

// 监听窗口关闭的事件,关闭的时候退出应用
macOs 需要排除 app.on('window-all-closed', () => {
if (process.platform !== 'darwin') { app.quit(); }
});

// Macos 中点击 dock 中的应用图标的时候重新创建窗口
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});

主进程 和 渲染进程中使用 Nodejs 以及 Nodejs 第三方模块

  • 主进程中无需任何配置就可以使用 nodejs 模块。
  1. BrowserWindow 中通过 preload 加载的 js 文件可以直接使用 nodejs 模块。
  2. 如果不使用 preload 加载的 jsElectron5.x 之后没法在渲染进程中直接使用 nodejs , 如果我们想在渲染进程中使用 nodejs 的话需要进行如下配置。
mainWindow=new BrowserWindow({
width:800,
height:600,
webPreferences: {
nodeIntegration: true,
contextIsolation:false
}
});

BrowserWindow 中通过 preload 加载的 js 文件可以直接使用 nodejs 模块

  • 在页面运行其他脚本之前预先加载指定的脚本 无论页面是否集成 Node , 此脚本都可以访 问所有 Node API 脚本路径为文件的绝对路径。
const createWindow = () => { 
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences:{
preload:path.join(__dirname, "renderer/preload.js")
}
});

mainWindow.loadFile(path.join(__dirname, "index.html"));
}
renderer/preload.js 渲染进程代码
const fs =require("fs"); 
fs.readFile("package.json", (err, data) => {
if (err) {
console.log(err)
return;
}
console.log(data.toString());
})

渲染进程中直接使用 Nodejs 模块

mainWindow=new BrowserWindow({
width:800,
height:600,
webPreferences: {
nodeIntegration: true,
contextIsolation:false
}
});
主进程

const { app, BrowserWindow } = require("electron");
const path = require("path");
const createWindow = () => {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences:{ // preload:path.join(__dirname, "renderer/preload.js"),
nodeIntegration:true,
contextIsolation:false
}
});

mainWindow.loadFile(path.join(__dirname, "index.html")); //打开 DevTools
mainWindow.webContents.openDevTools();
}

渲染进程

const fs =require("fs");
fs.readFile("package.json",(err ,data) => {
if (err) {
console.log(err);
return;
}
console.log(data.toString());
})

渲染进程和主进程中使用 Nodejs 第三方模块

  1. 安装模块
  2. 引入模块
  3. 参考第三方文档使用

开启调试模式

开启调试模式
mainWindow.webContents.openDevTools();
完整代码
const { app, BrowserWindow } = require("electron"); 
const path = require("path");
const createWindow = () => {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences:{
nodeIntegration: true,
contextIsolation: false
}
});

mainWindow.loadFile(path.join(__dirname, "index.html")); //打开 DevTools
mainWindow.webContents.openDevTools();

}
渲染进程中使用 nodejs 模块的案例
  1. 创建预加载脚本,并在其中使用 contextBridge 暴露 fs 功能。
preload.js
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
readFile: (filePath) => ipcRenderer.invoke('read-file', filePath)
});
  1. 在主进程中创建 BrowserWindow 时指定预加载脚本。
main.js
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true // 推荐开启上下文隔离
}
});
  1. 在主进程中处理 IPC 事件。
main.js
ipcMain.handle('read-file', async (event, path) => {
const fs = require('fs');
const data = fs.readFileSync(path, 'utf8');
return data;
});
  1. 在渲染进程中通过暴露的 API 调用功能。

window.electronAPI.readFile('文件路径').then((data) => {
console.log(data);
});

IPC事件

  • IPC事件 (Inter-Process Communication events)指的是在不同进程之间进行通信的事件。 在许多应用程序中,特别是在使用 Electron 这样的框架开发桌面应用时,IPC 事件是一个关键概念。

在 Electron 中的 IPC

  • Electron 框架中,IPC 事件被广泛用于在 主进程(Main Process)渲染进程(Renderer Process) 之间进行通信。

  • 主进程:运行包管理和窗口控制的 Node.js 进程。

  • 渲染进程:类似于 Web 浏览器中的标签页,它是一个展示用户界面的 Web 页面。

由于安全原因,这两种类型的进程在 Electron 中是隔离的,因此需要一种机制来进行通信。这就是 IPC 事件的作用。

IPC事件的工作原理

  1. 发送方:一个进程(发送方)通过发送 IPC 事件来请求信息或触发在另一个进程(接收方)中的操作。
  2. 接收方:接收方监听这些事件,并在事件发生时作出响应。
  3. 数据交换:IPC 事件可以携带数据,使进程间的通信更加灵活。

Electron中的IPC模块

Electron 提供了两个模块来支持 IPC

ipcMain :在主进程中使用,用于监听来自渲染进程的消息。 ipcRenderer:在渲染进程中使用,用于发送消息到主进程和从主进程接收消息。

示例

假设你在渲染进程中有一个按钮,点击后需要在主进程中执行某个操作:


const { ipcRenderer } = require('electron');

// 发送一个IPC事件到主进程
ipcRenderer.send('perform-action', { /* 数据 */ });

在主进程(ipcMain)

const { ipcMain } = require('electron');

// 监听来自渲染进程的IPC事件
ipcMain.on('perform-action', (event, args) => {
// 执行操作...
});

IPC事件是在不同进程间进行通信的重要机制,特别是在Electron这种多进程架构的应用中。它允许数据和消息在应用的不同部分之间安全地传递。