electron进程间通信之预加载脚本

通过前面的学习,我们知道在Electron中,主进程和渲染进程是被换分成不同的功能的,主进程有完整的Node环境,而渲染进程默认是运行的是浏览器环境。这样划分的好处是:

  1. 安全性:渲染进程运行在沙盒环境中,限制了对底层操作系统的访问和敏感资源的操作。直接在渲染进程中开启 Node.js 环境可能会带来潜在的安全风险,因为 Node.js 具有强大的功能和系统级访问权限,可能会被恶意利用或不当使用。

  2. 性能:渲染进程主要负责显示用户界面,处理用户交互和渲染页面。将 Node.js 环境直接放在渲染进程中可能会对性能产生负面影响,因为 Node.js 的运行环境相对较重,可能会消耗大量的内存和 CPU 资源,从而影响渲染进程的响应性能和用户体验。

  3. 分离关注点:主进程和渲染进程在 Electron 中有不同的职责和关注点。主进程负责管理应用程序的生命周期、系统级功能和与底层操作系统的交互,而渲染进程负责处理用户界面和与用户的交互。通过进程间通信,可以保持这种分离,使代码更易于维护、调试和扩展。

但是我们知道,开发的时候,我们很可能需要在渲染进程中进行一些只能在主进程中运行的操作。这就需要进程间通信了,在渲染进程中需要的时候,可以给主进程发信息,让主进程帮忙处理。

我们之前说过一种直接给渲染进程开启node环境,使用remote模块的方式,并不十分推荐。

预加载脚本(preload

Electron 不推荐在渲染进程开启Nodejs 环境,那也就意味着我们无法在渲染进程中使用NodeJS API,但有时候我们又真的很需要使用NodeJS API。“Preload 脚本”就是用来解决这个问题的。

用大白话来说就是:我们可以在主进程创建窗口的时候,指定一些脚本(内容是我们定的),这些脚本将来是在渲染进程中使用的,但是先于网页内容加载,由于是在主进程的时候就预加载了,所以能使用NodeJS API。

从 Electron 20 开始,预加载脚本默认 沙盒化 ,不再拥有完整 Node.js 环境的访问权,实际上,这意味着我们只拥有一个 require 函数,这个函数只能访问一组有限的 API。

可用的 API详细信息
Electron 模块仅限渲染进程模块
Node.js 模块eventstimersurl
Polyfilled 的全局模块BufferprocessclearImmediatesetImmediate

目前我使用的electron 的版本是 v25。下面写个示例体验一下:

  1. 创建一个预加载脚本 p1.js,我们可以在里面编写我们的代码,此脚本中可以使用Nodejs API。

    // p1.js
    const { contextBridge } = require('electron')
    // 将xxxx对象暴露给渲染进程中的全局对象,以便在渲染进程中直接访问
    contextBridge.exposeInMainWorld('xxxx', {
       name: '如花',
       run: function () {
           return '小子你跑的真快'
       }
    })
    contextBridge.exposeInMainWorld(apiKey, apiObject)

    此方法将指定的 apiObject 对象暴露给渲染进程中的全局对象,以便在渲染进程中直接访问。apiKey 是一个字符串,用于在全局对象中创建一个属性,该属性将指向 apiObject

  2. 创建窗口的时候,指定preload配置

    // main.js
    const win = new BrowserWindow({
     width: 800,
     height: 600,
     webPreferences: {
       // 配置预加载脚本(这里需要是个绝对路径)
       preload: path.join(__dirname, 'p1.js')
     },
    })
    win.loadFile('index.html')
  3. 在渲染进程中使用预加载脚本暴露的方法

    <!--index.html-->
    <!DOCTYPE html>
    <html lang="en">
    <head>
       <meta charset="UTF-8">
       <meta http-equiv="X-UA-Compatible" content="IE=edge">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>您好,世界</title>
    </head>
    <body>
       <h1>您好,世界!</h1>
       <script>
           // 调用预处理脚本中暴露的数据
           console.log(xxxx.name);
           console.log(xxxx.run());
       </script>
    </body>
    </html>


参考文档:https://www.electronjs.org/zh/docs/latest/tutorial/tutorial-preload


微信 遇到疑问可加微信进行反映