• Electron webview 内网页 与 preload、 渲染进程、主进程的常规通信 以及企业级开发终极简化通信方式汇总


    Electron 嵌入的页面中注入的是 preload.js

    通过在标签中给 prelaod赋值,这里提到了 file://前缀,以及静态目录 static 怎么获取

     实际代码,其中__static就是我们存放静态文件的地方,这个 static 是 electron 源代码根目录下的文件,最终打完包后会放在 dist/electron/ 根目录下

     而__static 是在index.html 中进行赋值的

     这里看,因为渲染进程会直接启动 index.html 这个文件,同时渲染进程又能调用 node.js 库,因此这里拿到的__static就是安装目录下的 static,因为这个 static 在asar压缩包里,所以这里就必须使用 file://{__static},否则读不到asar 的虚拟目录路径

    ChatGPT 虚拟目录概念:asar 可以进行解压,具体执行命令即可,后面详细研究后,再发文章

    1. 虚拟目录是一种将文件和文件夹组织成虚拟结构的方式,这些文件和文件夹在物理存储介质上(如硬盘)可能并不按照实际目录结构存储。在计算机科学和软件开发中,虚拟目录的概念是指一种将文件或数据组织成层次结构,使其看起来像是存储在目录结构中,但实际上可以是物理存储介质上的一个单一文件或数据库。
    2. 在 Electron 中,asar 存档就是一种虚拟目录的实现方式。asar 存档将应用程序的文件和文件夹组织成虚拟目录结构,这些文件和文件夹存储在一个单一的存档文件中,而不是以普通的文件和目录的形式存在于文件系统中。
    3. 这种虚拟目录结构的优点是:
    4. 减小应用程序的体积:asar 存档允许将所有文件打包成一个文件,减小了应用程序的体积,使得分发和部署更加方便。
    5. 加速文件访问:由于文件被打包成一个存档文件,文件的加载速度更快,因为它们可以被一次性加载到内存中,而不需要多次访问物理存储介质。
    6. 组织和保护文件:asar 存档允许将文件和文件夹组织成有层次结构的虚拟目录,这有助于更好地组织和保护应用程序的文件。
    7. 虚拟目录的概念使得开发者能够以更灵活的方式管理文件和数据,同时提高应用程序的性能和可维护性。在 Electron 中,asar 存档用于将应用程序文件组织成虚拟目录结构,以提高应用程序的性能和效率。

    webview 与被嵌入的渲染进程通信

    preload.js 就像插件的 content script 与网页的原生的环境还是隔离的,两个环境的变量互不影响,比如在 preload.js给 window 追加一个函数A,在原生网页中window.A 是 undefined,所以 preload.js 是沙盒环境

    但 preload.js(被注入网页中)中可以与其嵌入的 webview 容器进行通信,具体就是监听 ipc-message,接收渲染进程的消息,同时 webview还能通过 webview.send('ping') 给preload.js环境发送消息,这样就实现了 webview 容器中的网页与 webview 之间的通信过程

    1. // In embedder page.
    2. const webview = document.querySelector('webview')
    3. webview.addEventListener('ipc-message', (event) => {
    4. console.log(event.channel)
    5. // Prints "pong"
    6. })
    7. webview.send('ping')

    preload.js 所在的页面叫 guest page(访客页)

    1. // In guest page.
    2. const { ipcRenderer } = require('electron')
    3. ipcRenderer.on('ping', () => {
    4. ipcRenderer.sendToHost('pong')
    5. })

    webview 容器内页面 与 preload.js 通信

    如果在 guest page 中用 `webview.executeJavaScript(js代码)` 这样在 window.A下就可以访问到,但是两个环境之间有怎么进行通信呢?

    参考插件的content script 和 inject 的通信方式:

    1. 一是通过 window.postMessage 和 window.addEventListener("message", callback),这一种要把所有的事件都在一个 message 函数中处理,比较麻烦,如果不使用反射机制,就会将代码写得很长,有很多 if 判断;

    2. 二是通过事件 window.dispatchEvent(new CustomEvent('INJECT_READY')) 和 window.addEventListener("INJECT_READY", callback)  这种方式就好一些,可以将监听事件封装成具体的函数,引入处理,代码比较隔离

    3. electron 还给出了一种可以直接从 preload.js暴露函数给 window 的方式,这种非常方便:

    通过这样进行调用

    await window.electron.getAttachment(local_path, attachment.oss_path)

    webview 和主进程通信

    1. 借助被嵌入的渲染进程与主进程通信,这个就不细说了。

    1. // 主进程代码
    2. ipcMain.on("win-auto-update", (event, arg) => {})
    3. // 渲染进程代码
    4. ipcRenderer.send("win-auto-update")
    5. // 渲染进程与渲染进程通信
    6. ipcRenderer.sendTo(wid, "win-auto-update", {...})
    7. // 渲染进程监听消息
    8. ipcRenderer.on("win-auto-update", (event, args) => {})
    9. // event 对象中能够获得消息的来源是从哪个渲染进程发过来的

    解决一切苦厄的终极通信

    1. 在主进程中启动 Websocket 、Http 服务,Http 服务可以帮助用来从主进程访问本地数据库,Websocket 可以用来直接接收 webview preload 还是executeJavaScript,都可以通过 websocket 客户端直连主进程,主进程收到后,可以进行转发操作,过程中可以使用 Promise实现 await wsRequest 方式。这样整个链路就缩短为只需要直连任何一个进程的概念,就不用转来转去了,同时还能用 await 保证逻辑执行顺序,不因为通信延时无法控制 UI 表现层问题。

    具体我后面整理OK 后,再发一个代码 Demo 吧,有提前需要的也可以私信我。

  • 相关阅读:
    技术栈 业务架构 插件库
    如何防止金融防欺诈?
    2022杭电多校联赛第七场 题解
    ES6 类
    绝绝子还是YYDS,2021国民年度流行语出炉
    C#邮件发送
    QGIS编译(跨平台编译)之五十五:Qt Creator环境下libdxfrw库的pro文件
    如何在 LaTeX 中画一个树状图(使用tikz和tikz-qtree包中的宏绘制树、森林、二叉树)
    批量替换文本中的多组字符串
    Qt程序设计-柱状温度计自定义控件实例
  • 原文地址:https://blog.csdn.net/wangsenling/article/details/133884639