前言
这是入职之后,在公司项目中,梳理的jssdk封装的方案,其中一些方法例如:ipcRenderer.sendTo()已经在新版的eletron中弃用,其中的方案仅供学习。有不对的地方也欢迎各位大佬指正
弃用:
ipcRenderer.sendTo()
ipcRenderer.sendTo()
已被弃用。 可以通过在渲染器之间设置一个MessageChannel
来替换它。IpcRendererEvent
的senderId
和senderIsMainFrame
属性也已被弃用
后面,项目中还引入了模块联邦,这一块还没有梳理到,我会在之后补充进文档当中。
一、SDK工作流程图
什么是jssdk?它描述是一个工具集合,能够帮助我们快速调用各种能力,其包含了各种api,有自己的api文档和调用案例。
二、SDK整体架构设计
sdk主要配置路径/src/11-renderer/_public/sdk
其目录架构组成为:

2.1、通信桥接层
在/msgbridge.ts文件下,这里负责处理收到的postmsg,处理不同窗口间的postMessage通信,同时支持webView和BrowserView等场景(还有模块联邦)的通信,进行统一的消息处理、参数处理和api鉴权。
webView
ts
// 处理发送postmg
// containerId:目标窗口id
// msgdata:传递的参数
export function handlePostMessage({ msgdata, containerId }: { msgdata: any; containerId: any }) {
const { url, webview } = getWebviewUrl(containerId);
webview && webview.contentWindow.postMessage(msgdata, url);
}
BrowserView
ts
function handleBrowserViewMessage({ msgdata, containerId }: { msgdata: any; containerId: any }) {
window.ELECTRONCHANNEL &&
window.ELECTRONCHANNEL.electronBrowserviewSendToData({ ...msgdata, view_id: containerId });
}
2.2. 状态管理层
/redux.js 进行状态管理适配,可以根据不同的apicaller动态加载对应的redux模块
2.3. API层
csharp
api/
--biz/ # 业务相关API
-- util/ # 工具类API
-- chat/ # 聊天相关
-- contact/ # 联系人相关
-- group/ # 群组相关
-- navigation/ # 导航相关
--device/ # 设备相关API
--runtime/ # 运行时API
--primary/ # 基础API
--noPoint/ # 免鉴权API
--util/ # 通用工具
2.4. 文件处理系统
/file目录下封装了对文件的处理的方法,比如视频转码、视频播放、文件预览、文件下载等功能
2.5. 事件系统
在目录/yach-event下,封装了ai助手调用、addContentToEditor、toggleAddPrompt等方法。

三、如何建立通信
通信的建立包括四个步骤:preload脚本注入、H5调用、Yach接收调用、H5接收返回。
大致流程图如下:

从两种情况出发,webView和BrowserView,在我们注入脚本的时候,sendTo和sendToHost两个方法的应用场景也不同。
3.1 sendTo
官方:ipcRenderer.sendTo() 已被弃用。 可以通过在渲染器之间设置一个 MessageChannel 来替换它。
需要明确指定目标渲染进程的容器id
javascript
ipcRenderer.sendTo(win.id, '事件名', JSON.stringfy(data))
大致通信过程
1、主进程获取容器id并且发送给需要通信的进程
ts
// 主进程
const winA = new BrowserWindow();
const winB = new BrowserWindow();
// 向 winA 传递 winB 的 ID
winA.webContents.send('target-id', winB.webContents.id);
2、渲染进程A向进程B发送消息
ts
//渲染进程A
ipcRenderer.on('target-id', (event, targetId) => {
ipcRender.sendTo(targetId, 'test', '这是A发送的消息')
})
3、渲染进程B接收消息
ts
//渲染进程B
ipcRenderer.on('test', (event, message) => {
console.log(message)//输出这是A发送的消息
})
3.2 sendToHost
无需指定目标容器id,默认发送给当前渲染进程的"主容器"(通常是主进程创建的容器页面)
arduino
ipcRenderer.sendToHost('事件名', '消息');
大致通信流程
1、渲染进程
ts
// 渲染进程(网页)
ipcRenderer.sendToHost('test', '这是渲染进程的消息');
2、主进程进行监听并且处理
ts
const win = new BrowserWindow({
webPreferences: { nodeIntegration: false}// 限制渲染进程权限
});
//监听sendToHost发送的消息
wind.webContents.on('ipc-message',(event, channel, args) => {
if(channel === 'test'){
//处理并返回结果
event.sender.sendToHost('result', {list: [...]})
}
})
3、渲染进程接收宿主消息
ts
//渲染进程
ipcRenderer.on('result', (event, data) => {
console.log(data); //输出: 主进程返回的list
})
3.3 webView
webView是一个嵌入在渲染进程中的"子浏览器窗口",内部运行独立的渲染进程,且具有严格的沙箱隔离。通常使用senToHost方法。
webView内部页面的"宿主"是外层的渲染进程或者主进程,sendToHost设计的初衷就是让子页面向宿主发送消息,无需关心宿主的具体窗口id,简化通信链路。
3.4 browserView
browserView是由主进程创建、直接挂载到主窗口的"原生视图",没有独立的沙箱,其通信通过主进程的webContents直接交互,通常使用sendTo方法
browserView是由主进程管理,其webContent有明确的id,可以通过browserView。webContent.id获取。主进程或者其他渲染进程可通过sendTo(id, message)直接向其发消息。