跳到主要内容

Electron

Electron是由github开发,用HTML/CSS/JS来构建的跨平台桌面端应用 Electron通过将Chromium和Node.js合并到同⼀个运行时环境中,并将其打包为Mac, Windows和Linux系统下的应⽤来实现这⼀目的。

Chromium: 是一个开源的Web浏览器项目,它是Google Chrome浏览器的基础 Chromium用于渲染应用程序的界面,支持HTML、CSS和JavaScript,使得应用的用户界面看起来和行为类似于Web应用 Node.js提供了与操作系统交互的能力

  • electron开发桌面端有很大的优势
    • 前端工程化、前端的第三方库、前端生态
  • 使用前端语言开发
  • 一套代码开发 支持3个平台通用

缺点​

  • 性能差、体积大
    • 可能用户体验比较差, 程序运行缓慢

镜像加速​

环境搭建​

  • 安装electron包
bash
npm init -y
npm install electron --save-dev
  • package.json的script
    • "start": "electron ."

创建页面​

  • 在Electron中,各个窗口显示的内容可以是本地HTML文件,也可以是一个远程url。

快捷键​

  • Electron 应用中打开控制台的方法
    • 快捷键:按 Ctrl + Shift + I(Windows/Linux)或 Cmd + Option + I(Mac)
    • 菜单栏:点击 视图 → 开发者 → 开发者工具

调试技巧​

  • 1、nodemon
    • 可以监听electron主进程文件变化并自动重新启动进程
  • 2、vscode调试可以配合nodemon
    • 每次调试都可以自动启动进程

vscode debug调试配置​

参考文档

js
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Main Process",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
},
"args" : ["."],
"outputCapture": "std"
}
]
}

控制渲染进程样式​

  • 1、通过css控制
  • 2、BrowserWindow配置项
    • transparent: true
      • 设置透明
    • frame:false
      • 设置无框、无标题栏
      • frame用于设置窗口外壳
  • 3、BrowserWindow方法,内置了操作窗口的样式方法
    • win.setAspectRatio 控制窗口比例
    • win.setSize 控制窗口大小
    • .....

使用css控制拖拽​

默认情况下, 无边框窗口是不可拖拽的。 应用程序需要在 CSS 中指定 -webkit-app-region: drag

  • 需在 BrowserWindow 的构造中将 frame 参数设置为 false, 设置为无框窗口,才能让body拖动
    • 设置了frame表示窗口为无框、无标题栏,无法使用标题栏来拖动,只能通过body
  • 注意有些组件需要设置不能拖动,否则原有的一些事件无法触发
js
#js
const win = new BrowserWindow({ frame: false })

# style.css

body {
-webkit-app-region: drag; // 使该区域能拖拽
}

// 注意有些组件需要设置不能拖动,否则原有的一些事件无法触发
textarea,button {
-webkit-app-region: no-drag;
}

body {
width: 100vw;
height: 100vh;
}

渲染进程使用Node模块​

Electron为了安全性的考虑,是渲染子进程不能使用node.js模块的,如果要在渲染进程中使用node.js模块,需要在创建主进程时进行设置

  • 1、配置webPreferences的 nodeIntegration设置为true, 【启用node模块】
  • 2、设置contextIsolation: false 【控制渲染进程 是否为沙箱模式】
    • 控制渲染进程中是否启用沙箱模式。如果设置为 true,则渲染进程中的 JavaScript 代码将运行在一个独立的沙箱环境中,无法访问 Node.js 模块和原生 API,只能通过 Electron 提供的 API 与主进程进行通信。这可以提高应用程序的安全性,防止恶意代码对系统进行攻击

消息通道​

参考文档

  • 消息通道MessageChannel,可以在不同渲染进程之间进行通信的机制,建立了双向的通信管道
    • Message Channel 通过 MessageChannel 对象来创建,其中包括两个相关的 MessagePort 对象:port1 和 port2。
      • port1和port2这两个端口对象可以在不同的渲染进程之间进行传递和共享
  • 可以在渲染进程之间通过发送和接收消息来进行交互
    • 跨渲染进程的通信,可以使用 postMessage 方法发送消息,并通过 onmessage 事件来监听接收到的消息
  • 通过ipc方式,通过主进程去建立连接,在消息通道通过message、postMessage

消息通道应用场景​

  • 音频、视频
  • 获取数据任务 -> 处理数据
  • canvas渲染
    • 获取到后台数据之后,通过canvans来绘制图片来下载

Electron通信方式​

  • ipc通信 【可以应对绝大多数场景】
    • ipcRenderer.send 发送消息,然后使用 ipcMain.on 接收
    • 渲染进程向主进程传递参数
      • 在预加载脚本配合contextBridge,使用ipcRenderer.send发送消息,主进程通过ipcMain.on定义事件来接收参数
      • 主进程通过window对象来调用预加载脚本暴露的方法,来传递参数预加载脚本,预加载脚本再发参数传递给主进程
  • remote 【remote 模块在 Electron 12 废弃,并将在 Electron 14 被移除. 由@electronic/remote 模块替代,不推荐使用】
  • 消息通道 =>MessageChannel 【可以在渲染进程之间通信】
  • 通过预加载脚本 配合 contextBridge 【contextBridge提供安全机制可以使主进程与渲染进程通信,可以控制哪些api暴露】
  • 使用invoke/handle可以实现进程双向通信 【invoke理解为调用的意思, 调用主进程】
    • ipcRenderer.invoke 与 ipcMain.handle

预加载脚本​

注意,预加载脚本默认情况下,只提供了部分能使用electron的api、部分node模块

  • 可以设置sandbox为false、或者设置nodeIntegration为true, 就能使用electron和node其他模块了

由于Electron主进程可以完全操作系统的权限,为了避免渲染进程 直接调用主进程的方法 带来的安全问题,因此有了预加载脚本

  • 预加载脚本可以理解为桥梁,是主进程和渲染进程的之间访问桥梁
  • 通过预加载脚本,去访问主进程,把渲染页面的参数结果传递给渲染进程,在进行渲染页面
    • 虽然在预加载脚本可以访问DOM, 可以进行操作DOM, 渲染页面,但是不建议
      • 各司其职,操作DOM和渲染页面的操作,放在渲染进程去处理
  • 避免在渲染进程 直接使用nodejs模块和electron模块可能带来的安全风险
  • 预加载脚本提供了一种在渲染进程中安全地访问 Node.js 模块和 Electron API 的机制

预加载脚本何时注入?​

  • 预加载脚本在渲染进程加载网页之前注入

使用场景​

  • 提供全局变量或函数:预加载脚本可以在渲染进程中提供一些全局变量或函数,供你的应用程序中的所有渲染进程共享使用
  • 访问底层系统功能:预加载脚本可以使用 Node.js 模块和 Electron API 来访问底层系统功能,比如读取文件、执行 Shell 命令、操作系统原生通知等
  • 加强安全性:通过预加载脚本,你可以将某些敏感的 Electron API 功能封装在主进程中,并只将必要的功能暴露给渲染进程
  • 主进程和渲染进程通信,配合contextBridge

使用​

  • 主进程中在webPreferences中的preload属性
js
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
  • preload.js
js
const fs = require('fs');

// 访问node模块
const content = fs.readFileSync('package.json', 'utf-8');
console.log('content', content);

// 不建议DOM操作在预加载脚本处理,此代码最好放在渲染进程中处理DOM相关,DOM相关放在渲染进程中 【应各司其职】
window.addEventListener('DOMContentLoaded', () => {
console.log('DOM加载完');
// 可访问dom, 一般在渲染进程中访问dom,不建议在预加载脚本访问
});

沙箱模式​

默认情况下,electron开启了沙箱模式,为了增强安全性,减少额外代码的风险

  • 沙箱模式的目的:沙箱模式可以隔离渲染进程,使其不能直接访问底层操作系统或 Node.js 模块。这有助于防止潜在的安全漏洞
  • 限制:在沙箱模式下,渲染进程/预加载脚本中 无法访问大多数 Electron模块和Node.js 模块

如何控制沙箱模式

  • 通过窗口对象的 sandbox和nodeIntegration都可以设置
js
const win = new BrowserWindow({
webPreferences: {
nodeIntegration: true, // 控制是否使用node模块
// contextIsolation: false,
// sandbox:false, 控制是否沙箱模式
},
});

任务栏中是否显示窗口 dock状态栏​

Dock 是 macOS 操作系统的功能,类似于 Windows 操作系统的任务栏或者 Linux 操作系统的面板。在 macOS 上,Dock 通常位于桌面底部/或者侧边,包含应用程序图标、文件夹图标、常用应用的快速启动图标等

  • 窗口对象BrowserWindow设置skipTaskbar属性
js
const win = new BrowserWindow({
skipTaskbar: true, // 任务栏中显示窗口
})
  • 在mac系统中,隐藏dock状态栏
js
// 隐藏 dock 中的图标 【针对macOS】
app.dock.hide()

桌面应用通知​

Notification模块

  • 可以允许使用自定义模板、图像和其他灵活的元素进行高级通知

安装程序图标​

mac​

  • 苹果系统的软件图标可以使用 png 或 icns

icns

  • 可以使用多种方式创建icns,比如 electron-icns 包生成,或使用 anyconv、 alltoall等网站将 png 转为 icns 格式,也可以使用 sips 命令生成icns 图标

icns图标是一种用于苹果 macOS 操作系统的图标文件格式。它是"图标套件"(Iconset)的一部分

window​

  • window 系统支持 png 与 icon 图片文件

核心概念​

主进程和渲染进程​

主进程在node环境、渲染进程在浏览器环境

  • 因此在渲染进程可以操作DOM, 主进程无法操作DOM

主进程​

Electron 运行 package.json 的 main 脚本的进程被称为主进程

  • 启动项目时运行的main.js脚本就是主进程,在主进程的脚本可以创建web页面的形式GUI, 主进程只有一个

GUI :图形用户界面 (Graphical user interface)

主进程职责

  • 创建渲染进程(可多个)
  • 控制了应用生命周期(启动、退出APP以及对APP做⼀些事件监听)
  • 调用系统底层功能、
  • 调用原生资源
  • 可调用的api 【Node.js API 、 Electron提供的主进程API(包括⼀些系统功能和Electron附加功能)】

渲染进程​

  • 每个页面都会运行自己的进程,这个进程就是渲染进程

渲染进程职责

  • 用HTML和CSS渲染界面
  • 用JavaScript做⼀些界面
  • 可调用的api 【DOM API、NodeJS API、Electron提供的渲染进程API】

主进程和渲染进程通信​

通过ipcMain、ipcRenderer模块来实现通信 【原理:事件订阅】

  • 通过IPC通信
    • IPC是基于事件传递

Inter-Process Communication(IPC,进程间通信)来实现主进程和渲染进程之间的通信,以及在主进程中的不同模块之间的通信。