Electron 主进程与渲染进程、预加载preload.js

在 Electron 中,主要控制两类进程: 主进程渲染进程

Electron 应⽤的结构如下图:

如果需要更深入的了解electron进程,可以访问官网 流程模型 文档。

主进程

  • 每个 Electron 应用都有一个单一的主进程,作为应用程序的入口点(主进程具有唯一性)。任何 Electron 应用程序的入口都是 main 文件,负责控制应用的生命周期、创建和管理窗口、与操作系统进行交互等。
  • 主进程在 Node.js 环境中运行,它具有 require 模块和使⽤所有 Node.js API 的能力。
  • 主进程的核心:使用 BrowserWindow 来创建和管理应用程序窗口。

main.js 中,打印:

typescript 复制代码
console.log(__dirname)
console.log('node版本:', process.versions.node)
console.log('chrome版本:', process.versions.chrome)
console.log('electron版本:', process.versions.electron)

在终端中输入结果如下:

注意 :在主进程中执行的console.log()语句,都在vs code 的终端中输出,不会在electron 应用中打印。

main.js 中,打印 window

typescript 复制代码
console.log(window)

报错:window is not defined...

渲染进程

每个 Electron 应用都会为每个打开的 BrowserWindow ( 与每个网页嵌入 ) 生成一个单独的渲染器进程。 洽如其名,渲染器负责 渲染 网页内容。

  • 每个 BrowserWindow 实例都对应⼀个单独的渲染进程。
  • 一个 Electron 窗口可以包含一个或多个渲染进程,每个渲染进程负责渲染网页内容并执行网页中的 JavaScript 代码。(关系类似于 浏览器、浏览器中的标签页)
  • 运行在渲染器进程中的代码,必须遵守网页标准。这意味着 渲染进程无权直接访问 require 或 使用 任何 Node.js API。
  • 渲染进程主要负责呈现用户界面、响应用户交互、执行网页中的业务逻辑等。

pages/index.html 中:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"
    />
    <title>Hello Electron!</title>
  </head>
  <body>
    <h1>Hello Electron!</h1>
    We are using Node.js 
    <span id="node-version"></span>, Chromium
    <span id="chrome-version"></span>, and Electron
    <span id="electron-version"></span>.
  </body>
  <script src="./render.js"></script>
</html>

pages/render.js 中:

typescript 复制代码
console.log(window)
console.log(process)

在应用窗口中查看打印结果:

window能成功打印,console.log(process)报错:process is not defined...

pages/render.js 中,不能访问 Node.js API。那么,该如何实现在index.html中展示chrome、node、electron的版本呢?

处于渲染器进程的用户界面,该怎样才与 Node.js 和 Electron 的原生桌面功能进行交互?

通过预加载脚本从渲染器访问Node.js

预加载(preload)脚本在 Electron 应用中起着重要的桥梁作用,它允许渲染进程安全地与主进程进行交互,同时增强了应用的安全性和性能。

预加载(preload)脚本 在渲染器进程加载之前加载,并有权访问两个 渲染器全局 (例如 windowdocument) 和 Node.js 环境。

预加载(preload)脚本是运行在渲染器进程中的,但它是在网页内容加载之前执行的。 这意味着它具有比普通渲染器更高的权限,可以访问 Node.js API ,同时也可以与网页内容进行更安全的交互。

创建一个名为 preload.js 的新脚本如下:

typescript 复制代码
// contextBridge:在隔离的上下文中创建一个安全的、双向的、同步的桥梁。
const {contextBridge} = require('electron')

// 暴露数据给渲染进程
contextBridge.exposeInMainWorld('aaaAPI', {
  version: process.version,
  versions: process.versions,
  num: 666
})

在主线程中引⼊ preload.js

typescript 复制代码
const { app, BrowserWindow } = require('electron')
// 导入 Node.js 的 path 模块
const path = require('node:path')

// 修改已有的 createWindow() 方法
function createWindow() {
  const win = new BrowserWindow({
    width: 500, // 窗口宽度
    height: 300, // 窗口高度
    autoHideMenuBar: true, // 隐藏菜单栏
    webPreferences: {
      // 此处只能使用绝对路径
      preload: path.join(__dirname, 'preload.js')
    }
  });

  // 在窗口中加载一个远程页面
  win.loadFile('./pages/index.html');
}

执行npm start,启动应用,打开应用的控制台。

可以看到pages/render.js打印的window

完善pages/render.js,在渲染进程中使用versions,实现在 pages/index.html 页面展示版本信息:

typescript 复制代码
let nodeDom = document.getElementById('node-version')
let chromeDom = document.getElementById('chrome-version')
let electronDom = document.getElementById('electron-version')

const { node, chrome, electron } = aaaAPI.versions

nodeDom.innerHTML = node
chromeDom.innerHTML = chrome
electronDom.innerHTML = electron

查看应用窗口渲染结果:

现在,项目的目录结构如下图所示:

注意: 预加载(preload)脚本只能访问部分 Node.js API,但是主进程可以访问全部API。此时,需要使用进程通信。

相关推荐
旧味清欢|几秒前
关注分离(Separation of Concerns)在前端开发中的实践演进:从 XMLHttpRequest 到 Fetch API
javascript·http·es6
热爱编程的小曾17 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin29 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox42 分钟前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
-代号95271 小时前
【JavaScript】十四、轮播图
javascript·css·css3
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼2 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX187302 小时前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员